掃黃機器人

謝一

製作動機

實體掃黃

線上掃黃

掃黃機制

建立字典

字串匹配

HASH

\(Hash(S) = S_0 * r^0 + S_1 * r^1 + \dots + S_n * r^n \ mod P\)

檢查 hash 值是否一樣就能判斷兩個字串是否相同

重疊問題?

檢查輸出字串中包含時:

import discord
r, mod = 283, 2147483647;
T = open("token.txt", 'r').read();
keyword = open("keyword.txt", 'r').read().split();
KW = [];
ints = discord.Intents.all();
bot = discord.Client(intents = ints);
def cut(S : str):
	T = "";
	for s in S:
		if ord(s) < 128 and (ord(s) < ord('a') or ord(s) > ord('z')):
			continue;
		else:
			T += s;
	return T;
def has(S : str):
	E = [];
	h, j, k, x = 0, 0, 0, 1;
	for i in range(len(S)):
		if S[i] >= 'a' and S[i] <= 'z':
			E.append(j);
			j += 1;
		else:
			j += 3;
	j = 0;
	S = S.encode("utf-8");
	for i in range(len(S)):
		if k < len(E) and i == E[k]:
			h = (h + (S[i] + 256) * x) % mod;
			k += 1;
		else:
			h = (h + S[i] * x) % mod;
		x = x * r % mod;
		j += 1;
	return [h, j];
def hsh(S : str):
	E, H = [], [0];
	j, k, x = 0, 0, 1;
	for i in range(len(S)):
		if S[i] >= 'a' and S[i] <= 'z':
			E.append(j);
			j += 1;
		else:
			j += 3;
	j = 0;
	S = S.encode("utf-8");
	for i in range(len(S)):
		if k < len(E) and i == E[k]:
			H.append((H[i] + (S[i] + 256) * x) % mod);
			k += 1;
		else:
			H.append(((H[i] + S[i] * x)) % mod);
		x = x * r % mod;
	return H;
def yellow(msg : str):
	S = hsh(msg);
	for [k, w] in KW:
		for i in range(1, len(S) - w + 1):
			if k == (S[i + w - 1] - S[i - 1] + mod) % mod:
				return 1;
			k = k * r % mod;
	return 0;
@bot.event
async def on_ready():
	for kw in keyword:
		KW.append(has(kw));
	print("logged in as", end = ' ');
	print(bot.user);
@bot.event
async def on_message(msg : discord.Message):
	if msg.author == bot.user:
		return;
	M = msg.content;
	M = cut(M.lower());
	if yellow(M):
		print("業績 + 1");
		await msg.channel.send(file = discord.File("swipe.png"));
		await msg.channel.send(file = discord.File("yellow.png"));
if __name__ == "__main__":
	bot.run(T);

實測時間

掃黃!!!

DigoliangNeverDie

Subtask 1: \(N \le 100\)

Enumerate \(l, r\) and find the minimum \(H_i \ (l \le i \le r)\), then compare all \(H_i \times (r - l + 1)\).

 

Time complexity: enumerate \(l, r \ \times\) find min = \(\mathcal{O}(N^2) \times \mathcal{O}(N) = \mathcal{O}(N^3)\)

Subtask 2: \(N \le 1919\)

Notice That:

For the same \(r\), we can decrease \(l\) from \(r\) to \(1\) and update the minimum \(H_i\) between \(l\) and \(r\) at the same time, which makes the time complexity drop to \(\mathcal{O}(N^2)\)

Subtask 3

For all \(i\), we only have to find the greatest \(l \ \text{s.t.} \ l < i \cap H_l < H_i\) and the smallest \(r \ \text{s.t.} \ i < r \cap H_r < H_i\), then the interval that height \(H_i\) can cover is \((l, r)\).

This can be done by a monotone stack in amortized \(\mathcal{O}(1)\) time.

Monotone Stack

push(\(H_i\)) : check if \(H_i\) is smaller than or equal to the top element, if true then the top element will never be used (since it is larger than or equal to \(H_i\) and has a smaller index than \(i\) so it will not be a \(l\) for any \(j > i\)), so we can pop it out and recursively check the top element until \(H_i\) is greater than the top element, which is also when \(H_i\) meets its \(l\).

Solution

For each \(i\), we can find its \(l\) in \(\mathcal{O}(N)\) time by monotone stack. To find \(r\), we only have to reverse to array and run again the same process.

Thus, the overall time complexity for this solution is \(\mathcal{O}(N)\)

#include <bits/stdc++.h>
#define int long long
#define ff first
#define ss second
using namespace std;
int H[11451481], L[11451481], R[11451481];
signed main(){
	cin.tie(0), cout.tie(0), ios::sync_with_stdio(0);
	int n, ans = 0;
	cin >> n;
	stack<pair<int, int>> S;
	S.push({-1, 0});
	for(int i = 1; i <= n; i++){
		cin >> H[i];
		while(H[i] <= S.top().ff) S.pop();
		L[i] = S.top().ss, S.push({H[i], i});
	}
	while(!S.empty()) S.pop();
	S.push({-1, n + 1});
	for(int i = n; i; i--){
		while(H[i] <= S.top().ff) S.pop();
		R[i] = S.top().ss, S.push({H[i], i});
	}
	for(int i = 1; i <= n; i++) ans = max(ans, (R[i] - L[i] - 1) * H[i]);
	cout << ans << "\n";
	return 0;
}

掃黃機器人

By thanksone

掃黃機器人

  • 360