AC自动机九连测

T 1 : 病 毒 侵 袭 T1:病毒侵袭 T1:

A C   C o d e \mathrm{AC \ Code} AC Code

#include<bits/stdc++.h>
#define maxn 100005
#define maxc 95
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--) 
using namespace std;

int total;
namespace AC{
   
	int tr[maxn][maxc],fa[maxn],tot;
	set<int>ed[maxn];
	
	void clr(){
   
		for(;tot;) memset(tr[tot],0,sizeof tr[tot]),ed[tot].clear(),fa[tot--]=0;
 	}
	
	void ins(char *s,int n,int id){
   
		int u=0,v;
		rep(i,0,n-1) (!tr[u][v=s[i]-32])&&(tr[u][v]=++tot),u=tr[u][v];
		ed[u].insert(id);
	}
	
	void Build(){
   
		static int q[maxn],L,R;
		rep(i,L=R=0,maxc-1) if(tr[0][i]) q[R++]=tr[0][i];
		for(int u;L<R;){
   
			u=q[L++];
			if(ed[fa[u]].size() <= 3)
				ed[u].insert(ed[fa[u]].begin(),ed[fa[u]].end());
			rep(i,0,maxc-1) 
				if(tr[u][i]) 
					q[R++]=tr[u][i],fa[tr[u][i]]=tr[fa[u]][i];
				else 
					tr[u][i] = tr[fa[u]][i];
		}
	}
	void qry(char *s,int n,int id){
   
		int u=0,v;
		set<int>r;
		rep(i,0,n-1) 
			u=tr[u][v=s[i]-32],
			r.insert(ed[u].begin(),ed[u].end());
		if(r.size()){
   
			total++;
			printf("web %d:",id);
			for(set<int>::iterator it=r.begin();it!=r.end();it++)
				printf(" %d",*it);
			putchar('\n');
		}
	}
}

int main(){
   
	int n;scanf("%d",&n);
	rep(i,1,n){
   
		static char s[205];
		scanf("%s",s);
		int m = strlen(s);
		AC::ins(s,m,i);
	}
	AC::Build();
	scanf("%d",&n);
	rep(i,1,n){
   
		static char s[10005];
		scanf("%s",s);
		int m = strlen(s);
		AC::qry(s,m,i);
	}
	printf("total: %d\n",total);
}

T 2 考 研 路 茫 茫 — — 单 词 情 结 \mathrm{T2 考研路茫茫——单词情结 } T2

A C   C o d e \mathrm{AC \ Code} AC Code

#include<bits/stdc++.h>
#define maxn 27
#define maxc 26
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
#define Ct const
#define LL unsigned long long
using namespace std;

int N;
struct mat{
   
	LL a[maxn][maxn];
	mat(LL d=0){
    memset(a,0,sizeof a);rep(i,0,maxn-1) a[i][i]=d; }
	mat operator *(Ct mat &B)Ct{
   
		mat r;
		rep(i,0,N-1) rep(j,0,N-1) if(a[i][j]) rep(k,0,N-1) if(B.a[j][k])
			r.a[i][k] += a[i][j] * B.a[j][k];
		return r;
	}
}A;

mat Pow(mat b,LL k){
   
	mat r(1);
	for(;k;k>>=1,b=b*b) 
		if(k&1)
			r=b*r;
	return r;
}

namespace AC{
   
	int tr[maxn][maxc],fa[maxn],sz;
	bool tag[maxn];
	void clr(){
   
		for(;~sz;) memset(tr[sz],0,sizeof tr[sz]),tag[sz]=0,fa[sz--]=0;
		sz=0;
	}
	
	void ins(char *s,int n){
   
		int u=0,v;
		rep(i,0,n-1) (!tr[u][v=s[i]-'a'])&&(tr[u][v]=++sz),u=tr[u][v];
		tag[u]=1;
	}
	
	void Build(){
   
		static int q[maxn],L,R;
		rep(i,L=R=0,maxc-1) if(tr[0][i]) q[R++]=tr[0][i];
		for(int u;L<R;){
   
			u=q[L++];
			tag[u] |= tag[fa[u]];
			rep(i,0,maxc-1) 
				if(tr[u][i]) 
					fa[tr[u][i]]=tr[fa[u]][i],q[R++]=tr[u][i];
				else
					tr[u][i] = tr[fa[u]][i];
		}
		N = sz+2;
		rep(i,0,sz) if(!tag[i])
			rep(j,0,maxc-1) if(!tag[tr[i][j]])
				A.a[i][tr[i][j]]++;
		rep(i,0,N-1) 
			A.a[i][N-1]++;
	}
}

LL cal(int L){
   
	LL a=1,b=26,ra=1,rb=26;
	for(;L;L>>=1,a=a+a*b,b*=b)
		if(L&1)
			ra=ra+a*rb,rb*=b;
	return ra;
}

int main(){
   
	int n,L;
	while(~scanf("%d%d",&n,&L)){
   
		AC::clr();A=mat(0);
		for(;n--;){
   
			static char s[6];
			scanf
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个基于AC自动机的敏感词检系统后端部分的C++代码: ```c++ #include <iostream> #include <vector> #include <queue> #include <cstring> using namespace std; const int MAXN = 10005; const int MAXM = 100005; int trie[MAXN][26], fail[MAXN], cnt = 0; // trie树,fail指针,节点计数器 int end[MAXN]; // 记录trie树上的单词节点 bool vis[MAXN]; // 记录访问过的节点 int n; // 敏感词的个数 char word[MAXM]; // 待检的字符串 vector<int> sensitive; // 记录敏感词的出现位置 void insert(char *s, int id) // 插入单词 { int p = 0; for (int i = 0; s[i]; i++) { int c = s[i] - 'a'; if (!trie[p][c]) trie[p][c] = ++cnt; p = trie[p][c]; } end[p] = id; } void buildAC() // 构建AC自动机 { queue<int> que; for (int i = 0; i < 26; i++) if (trie[0][i]) que.push(trie[0][i]); while (!que.empty()) { int u = que.front(); que.pop(); for (int i = 0; i < 26; i++) { int &v = trie[u][i]; if (v) { fail[v] = trie[fail[u]][i]; que.push(v); } else v = trie[fail[u]][i]; } } } void query() // 查询字符串中的敏感词 { int p = 0; for (int i = 0; word[i]; i++) { int c = word[i] - 'a'; p = trie[p][c]; for (int j = p; j && !vis[j]; j = fail[j]) { vis[j] = true; if (end[j]) sensitive.push_back(i - strlen(word) + 1); // 记录敏感词的出现位置 } } } int main() { cin >> n; for (int i = 1; i <= n; i++) { char s[MAXM]; cin >> s; insert(s, i); } buildAC(); cin >> word; query(); if (sensitive.empty()) cout << "No sensitive words found." << endl; else { for (int i = 0; i < sensitive.size(); i++) { for (int j = sensitive[i]; j < sensitive[i] + strlen(word); j++) cout << word[j]; cout << " is a sensitive word at position " << sensitive[i] << "." << endl; } } return 0; } ``` 在该程序中,我们先使用`insert()`函数构建了一颗Trie树,并在每个单词的最后一个字母节点上标记该单词的编号,以便查询时能够输出敏感词的编号。接着,我们使用`buildAC()`函数构建了AC自动机,并在自动机上使用BFS算法将每个节点的fail指针指向其失败路径上的最长可匹配后缀节点。最后,我们使用`query()`函数在自动机上查询待检的字符串,记录每个匹配到的单词节点,并输出其在字符串中的位置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值