题目:
1 5 6 orz sto kirigiri danganronpa ooooo o kyouko dangan ronpa ooooo ooooo
1 1 0 3 7
题意:字符串匹配,多个模式串匹配源串。
思路:AC自动机模板题。
代码:
//AC 自动机 #include <stdio.h> #include <string.h> #include <queue> using namespace std; inline int Max(int a,int b) { return a>b?a:b; } inline int Min(int a,int b) { return a>b?b:a; } #define maxnode 600010 #define sigma_size 26 struct Trie { int ch[maxnode][sigma_size];//下一指针 int val[maxnode];//匹配进度 int haha[maxnode];//节点i的成功匹配数 int f[maxnode];//失配指针 int sz;//size //初始化 void init() { sz=1; memset(ch,0,sizeof(ch)); memset(val, 0, sizeof(val)); memset(f,0,sizeof(f)); memset(haha,0,sizeof(haha)); } //字符 c 的 index int idx(char c) { return c-'a'; } //插入串 s int insert(char *s) { // int u = 0, len = strlen(s); for(int i = 0; i < len; i++) { //获取index int c = idx(s[i]); if(!ch[u][c]) ch[u][c] = sz++;//无路则建立指针到最后一个节点 u = ch[u][c];//到下一节点 } val[u] ++; //将串结束的位置的val++ return u; //返回串S 结束位置的指针 } //计算失败指针 void getFail() { queue<int> q; for(int i = 0; i<sigma_size; i++) if(ch[0][i]) q.push(ch[0][i]);//处理根节点 //将根节点的所有下一节点加入队列 while(!q.empty()) { int r = q.front(); q.pop(); //取队首为r //遍历r的所有下级 for(int c = 0; c<sigma_size; c++) { int u = ch[r][c]; if(!u)continue;//如果下一节点是根节点,跳过 //将r的下级加入队列 q.push(u); int v = f[r]; ///沿失配边走上去 如果失配后有节点 且 其子节点c存在则结束循环 while(v && ch[v][c] == 0) v = f[v]; f[u] = ch[v][c];//改变失配指针 } } } //匹配 串T void find(char *T) { int len = strlen(T), j = 0;//j为当前节点编号(0代表根节点) for(int i = 0; i < len; i++) { int c = idx(T[i]); while(j && ch[j][c]==0) //当j不是根节点且j到c无路(失配) j = f[j];//走失配指针到下一节点(回滚) //循环结束时: //j 为根节点 或 j到c有路(可配) j = ch[j][c];//j到下一节点,若j为根节点且没有路,则j还会走到根节点 int temp = j; //标记整个路上的 while(temp)//当temp不是根 { haha[temp]++;//在temp节点的进度+1 temp = f[temp];//回退到失败后节点 } } } }; Trie ac; char P[100011][10010]; int ans[100010]; char S1[100010]; int main() { int t,m,n; scanf("%d",&t); while(t--) { ac.init(); scanf("%d%d",&m,&n); for(int i = 1; i <= m; i++) { scanf("%s",P[i]); } for(int i = 1; i <= n; i++) { scanf("%s",S1); ans[i] = ac.insert(S1); } ac.getFail(); for(int i = 1; i <= m; i++) { memset(ac.haha,0,sizeof(ac.haha)); ac.find(P[i]); int sum = 0; for(int i=1; i <= n; i++) sum += ac.haha[ans[i]]; printf("%d\n",sum); } } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/u013840081/article/details/48070739