输出:依次按如下格式输出按网站编号从小到大输出,带病毒的网站编号和包含病毒编号,每行一个含毒网站信息。
web 网站编号: 病毒编号 病毒编号 …冒号后有一个空格,病毒编号按从小到大排列,两个病毒编号之间用一个空格隔开,如果一个网站包含病毒,病毒数不会超过3个。最后一行输出统计信息,如下格式:total: 带病毒网站数。冒号后有一个空格。思路:AC自动机模板题。只是需要注意有多个母串,所以用母串扫的时候一次找到不能将num数组置零,需要用其他办法。我用了一个flag数组记录。
特别注意的是:如果对整个trie用memset刷新初始值会MLE,如果使用过程中逐个初始化才能AC。
3065的题意类似,需要输出每个模式串出现的次数,查询的时候使用一个数组进行记录就可以了。这题又给了我一个教训,HDU的题目都是多组数据的,虽然题目里并没有说明。
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <cstdlib> using namespace std; #define INF 0x3fffffff #define N 100005 #define M 128 int t[N][M],fail[N],num[N],output[3],sum,flag[505]; char s[10005]; int n,m,top; queue<int> q; int newnode(){//必须这样初始化才能AC top++; for(int i = 0;i<M;i++) t[top][i] = -1; return top; } void init(){ memset(fail,0,sizeof(fail)); memset(num, 0, sizeof(num)); //memset(t, -1, sizeof(t));//这个地方要注意:直接memset一个数组就会超内存,写个newnode函数用到的时候一个个的初始化就不会超过。。。 memset(output, 0, sizeof(output)); for(int i = 0;i<M;i++) t[0][i] = 1; top = 0; newnode();//root节点 sum = 0; } void insert(char* s,int id){ int i,r = 1; for(i = 0;s[i];i++){ if(t[r][s[i]] == -1) t[r][s[i]] = newnode(); r = t[r][s[i]]; } num[r] = id; } void buildDFA(){ int i,now; q.push(1); while(!q.empty()){ now = q.front(); q.pop(); for(i = 0;i<M;i++){ if(t[now][i] == -1) t[now][i] = t[fail[now]][i]; else{ fail[t[now][i]] = t[fail[now]][i]; q.push(t[now][i]); } } } } bool search(char* s,int id){ int i,j,r = 1,ans = 0; memset(flag, 0, sizeof(flag)); for(i = 0;s[i];i++){ j = r = t[r][s[i]]; while(j){ if(num[j] && !flag[num[j]]){ output[ans++] = num[j]; flag[num[j]] = 1; } j = fail[j]; } if(ans == 3)//最多3个病毒 break; } if(!ans) return false; sort(output,output+ans); printf("web %d:",id); for(j = 0;j<ans;j++) printf(" %d",output[j]); putchar('\n'); return true; } int main(){ int i; while(scanf("%d",&n) != EOF){ init(); for(i = 1;i<=n;i++){ scanf("%s",s); insert(s,i); } buildDFA(); scanf("%d",&m); for(i = 1;i<=m;i++){ scanf("%s",s); if(search(s,i)) sum++; } printf("total: %d\n",sum); } return 0; }
3065:
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <cstdlib> using namespace std; #define INF 0x3fffffff #define N 50005 int t[N][27],fail[N],num[N],res[1005]; int n,top; char s[1005][55],b[2000005]; queue<int> q; int newnode(){ top++; for(int i = 0;i<27;i++) t[top][i] = -1; return top; } void init(){ memset(fail, 0, sizeof(fail)); memset(num, 0,sizeof(num)); memset(res, 0, sizeof(res)); for(int i = 0;i<27;i++) t[0][i] = 1; top = 0; newnode(); } void insert(char* s,int id){ int i,r = 1; for(i = 0;s[i];i++){ if(t[r][s[i]-'A'] == -1) t[r][s[i]-'A'] = newnode(); r = t[r][s[i]-'A']; } num[r] = id; } void buildDFA(){ int i,now; q.push(1); while(!q.empty()){ now = q.front(); q.pop(); for(i = 0;i<27;i++){ if(t[now][i] == -1) t[now][i] = t[fail[now]][i]; else{ fail[t[now][i]] = t[fail[now]][i]; q.push(t[now][i]); } } } } void search(char* s){ int i,r = 1,tmp; for(i = 0;s[i];i++){ if(!(s[i]>='A'&&s[i]<='Z')) s[i] = 'Z'+1; r = tmp = t[r][s[i]-'A']; while(tmp){ if(num[tmp]) res[num[tmp]]++; tmp = fail[tmp]; } } } int main(){ int i; while(scanf("%d",&n)!=EOF){ init(); for(i = 1;i<=n;i++){ scanf("%s",s[i]); insert(s[i],i); } buildDFA(); scanf("%s",b); search(b); for(i = 1;i<=n;i++) if(res[i]) printf("%s: %d\n",s[i],res[i]); } return 0; }