BZOJ 3172

BZOJ - 3172

题目中的文章是由所有单词拼出来的,但是单词直接互相独立

首先单词都丢进AC自动机,然后一个个跑匹配

每一次更新\(fail\)树上一段路径前缀的节点即可

事实上就是在哪里放一个1,按次向根累加就能得到答案

int n;
int l;
string s[N];
int End[N];

const int SIZE=N;
int trie[N][26],fail[N],cnt;
int Insert(string &s){
	int p=0;
	rep(i,0,s.size()-1) {
		int x=s[i]-'a';
		if(!trie[p][x]) trie[p][x]=++cnt;
		p=trie[p][x];
	}
	return p;
}

int line[SIZE],Ans[SIZE],lc;
void Build(){
	static queue <int> que;
	rep(i,0,25) if(trie[0][i]) que.push(trie[0][i]);
	while(!que.empty()){
		int u=que.front(); que.pop();
		line[++lc]=u;
		rep(i,0,25) {
			int &v=trie[u][i];
			if(v) {
				que.push(v);
				fail[v]=trie[fail[u]][i];
			} else v=trie[fail[u]][i];
		}
	}
}





int main(){
	ios::sync_with_stdio(false);
	cin>>n;
	rep(i,1,n) {
		cin>>s[i];
		End[i]=Insert(s[i]);
	}
	Build();
	rep(i,1,n){
		int p=0;
		rep(j,0,s[i].size()-1) {
			p=trie[p][s[i][j]-'a'];
			Ans[p]++;
		}
	}
	drep(i,lc,1) Ans[fail[line[i]]]+=Ans[line[i]];//利用广搜序累和
	rep(i,1,n) printf("%d\n",Ans[End[i]]);
}
原文地址:https://www.cnblogs.com/chasedeath/p/12931297.html