标签:return round 多次 ott while put iostream string 多少
Description
某人读论文,一篇论文是由许多单词组成.但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次.
Input
第一个一个整数N,表示有多少个单词.
接下来N行每行一个单词,每个单词由小写字母组成.
Output
输出N个整数,第i行的数字表示第i个单词在文章中出现了多少次.
Sample Input
3Sample Output
6
3
1
HINT
N$\leq$200,单词总长度不超过$10^6$
Solution
AC自动机+fail树.
fail树中求子树和即可.
#include<cmath> #include<ctime> #include<queue> #include<stack> #include<cstdio> #include<vector> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define M 26 #define K 205 #define N 1000005 using namespace std; struct trie{ int chl[M],nxt,cnt; }t[N]; struct graph{ int nxt,to; }e[N]; int a[K],g[N],tot[N],n,m,cnt; char c[N]; queue<int> q; inline void addedge(int x,int y){ e[++cnt].nxt=g[x];g[x]=cnt;e[cnt].to=y; } inline int insert(int u,int i){ ++t[u].cnt; if(i==m) return u; int k=c[i]-‘a‘; if(!t[u].chl[k]) t[u].chl[k]=++cnt; return insert(t[u].chl[k],i+1); } inline void get_nxt(){ for(int i=0;i<M;++i) if(t[0].chl[i]) q.push(t[0].chl[i]); while(!q.empty()){ int u=q.front();q.pop(); for(int i=0,j,c;i<26;++i) if(c=t[u].chl[i]){ q.push(c);j=t[u].nxt; while(j&&!t[j].chl[i]) j=t[j].nxt; t[c].nxt=t[j].chl[i]; } } } inline void ask(int u){ tot[u]=t[u].cnt; for(int i=g[u];i;i=e[i].nxt){ ask(e[i].to);tot[u]+=tot[e[i].to]; } } inline void Aireen(){ scanf("%d",&n); for(int i=1;i<=n;++i){ scanf("%s",c); m=strlen(c); a[i]=insert(0,0); } get_nxt();m=cnt;cnt=0; for(int i=1;i<=m;++i) addedge(t[i].nxt,i); ask(0); for(int i=1;i<=n;++i) printf("%d\n",tot[a[i]]); } int main(){ freopen("word.in","r",stdin); freopen("word.out","w",stdout); Aireen(); fclose(stdin); fclose(stdout); return 0; }
标签:return round 多次 ott while put iostream string 多少
原文地址:http://www.cnblogs.com/AireenYe/p/6219961.html