Singing Superstar HDU - 7064
题意:
问在串T中出现了几次不相交的串S?
每次有n个串S询问
题解:
AC自动机板子题。。
直接上模板
代码:
#include <bits/stdc++.h>
#include <unordered_map>
#define debug(a, b) printf("%s = %d\n", a, b);
using namespace std;
const int maxnode= 5e5;
const int sigma_size= 26;
int ans= 0;
template <typename T> inline void read(T& x)
{T f= 1;x= 0;char ch= getchar();while (0 == isdigit(ch)) {if (ch == '-')f= -1;ch= getchar();}while (0 != isdigit(ch))x= (x << 1) + (x << 3) + ch - '0', ch= getchar();x*= f;
}
template <typename T> inline void write(T x)
{if (x < 0) {x= ~(x - 1);putchar('-');}if (x > 9)write(x / 10);putchar(x % 10 + '0');
}
struct AC_Automata
{int ch[maxnode][sigma_size];int val[maxnode]; // 以单词结尾的个数int f[maxnode]; // fail函数int last[maxnode]; // last[i]=j表j节点表示的单词是i节点单词的后缀,且j节点是单词节点int sz;int cnt[maxnode]; //非单词节点vis=0,单词节点vis=1.如果用find找到了单词i节点,那么vis=0.int pos[maxnode], len[maxnode];void init(){sz= 1;memset(ch[0], 0, sizeof(ch[0]));val[0]= 0;last[0]= f[0]= 0;memset(cnt, 0, sizeof(cnt));memset(pos, 0, sizeof(pos));memset(len, 0, sizeof(len));}void insert(char* s){int n= strlen(s), u= 0;for (int i= 0; i < n; i++) {int id= s[i] - 'a';if (ch[u][id] == 0) {ch[u][id]= sz;memset(ch[sz], 0, sizeof(ch[sz]));val[sz++]= 0;}u= ch[u][id];}val[u]= 1;len[u]= n;}void getFail(){queue<int> q;last[0]= f[0]= 0;for (int i= 0; i < sigma_size; i++) {int u= ch[0][i];if (u) {f[u]= last[u]= 0;q.push(u);}}while (!q.empty()) {int r= q.front();q.pop();for (int i= 0; i < sigma_size; i++) {int u= ch[r][i];if (u == 0)continue;q.push(u);int v= f[r];while (v && ch[v][i] == 0)v= f[v];f[u]= ch[v][i];last[u]= val[f[u]] ? f[u] : last[f[u]];}}}void print(int i, int pos1){if (val[i]) {if (pos[i] + len[i] <= pos1) {pos[i]= pos1;cnt[i]++;}print(last[i], pos1);}}void find(char* s){int n= strlen(s), j= 0;for (int i= 0; i < n; i++) {int id= s[i] - 'a';while (j && ch[j][id] == 0)j= f[j];j= ch[j][id];if (val[j])print(j, i + 1);else if (last[j])print(last[j], i + 1);}}int find_T(char* s){int n= strlen(s), u= 0;for (int i= 0; i < n; i++) {int id= s[i] - 'a';u= ch[u][id];}return cnt[u];}
};
AC_Automata ac;char word[100080][50];
char s[100005];
int main()
{int n;int T;int cas= 0;read(T);while (T--) {scanf("%s", &s);scanf("%d", &n);ac.init();for (int i= 1; i <= n; i++) {scanf("%s", word[i]);ac.insert(word[i]);}ac.getFail();ac.find(s);for (int i= 1; i <= n; i++) {printf("%d\n", ac.find_T(word[i]));}}
}