字符串

大部分字符串的东西都会放在这篇。

待补。

KMP

大体思路:

主串和模式串进行挨个匹配。到了一个不匹配的,找该点前面的最长公共前后缀(且要小于子串长度),然后让前缀跳到后缀的位置。

当前位与主串比较,等于最大公共前后缀长度+1。

\(nxt[i]\) : 当第i位失配时,模式串的第\(nxt[i]\)位与当前位置比较。

code:

const int N=1e6+10;
char s1[N],s2[N];
int l1,l2,nxt[N];
signed main(){
	cin>>s1+1;
	cin>>s2+1;
	l1=strlen(s1+1);
	l2=strlen(s2+1);
//	nxt[0]=nxt[1]=1;
	int pos=0;//模式串
	//预处理nxt数组 
	rep(i,2,l2){
		while(pos&&s2[i]!=s2[pos+1]) pos=nxt[pos];//如果不匹配 直到匹配或=0为止 
		if(s2[pos+1]==s2[i]) ++pos;//如果匹配就更新 
		nxt[i]=pos;//更新nxt 
	}
	pos=0;
	rep(i,1,l1){//同理 
		while(pos&&s1[i]!=s2[pos+1]) pos=nxt[pos];
		if(s2[pos+1]==s1[i]) ++pos;
		if(pos==l2) {
			cout<<i-l2+1<<'\n';
			pos=nxt[pos]; 
		}
	}
	rep(i,1,l2) cout<<nxt[i]<<" ";
	return 0;
}

AC自动机

前置芝士:Trie,KMP,DP(思想。

AC 自动机是一类确定有限状态自动机,这说明它有完整的 DFA 五要素,分别是起点\(s\)(Trie 树根节点),状态集合 \(Q\)(Trie 树上所有节点),接受状态集合 \(F\)(所有以某个单词作为后缀的节点),字符集 \(Σ\)(题目给定)和转移函数 \(δ\)(类似 KMP 求解)。

AC 自动机全称 Aho-Corasick Automaton,简称 ACAM。

Key:

考虑用类似 KMP 的算法求解失配指针:首先令 \(fail_q←fail_{faq}\)。若当前的 \(fail_q\)没有 \(fa_q→q\) 这条(字典树上的)边所表示的字符 \(c\) 的转移,则令 \(fail_q←fail_{failq}\),否则\(fail_q=trans(fail_q,c)\),即字典树上在 \(fail_q\)处添加字符 \(c\) 后到达的状态。若 \(fail_q\)已经指向根,但还是没找到出边,则 \(fail_q\)
最终就指向根。

Code:

int n,cnt;
string s;
struct node{
	int fail,son[26],end;
}t[N];
void build(string s){//建立tire树 
	int l=s.length();
	int now=0;
	rep(i,0,l-1){
		if(t[now].son[s[i]-'a']==0)
		t[now].son[s[i]-'a']=++cnt;
		now=t[now].son[s[i]-'a'];
	}
	t[now].end+=1;
}
void Get_fail(){//构造fail 
	queue<int>q;
	rep(i,0,25){
		if(t[0].son[i]!=0){//预处理 
			t[t[0].son[i]].fail=0;//指向根 
			q.push(t[0].son[i]);
		}
	}
	while(!q.empty()){
		int now=q.front();
		q.pop();
		rep(i,0,25){
			if(t[now].son[i]!=0){//存在子节点 
				t[t[now].son[i]].fail=t[t[now].fail].son[i];//子节点的fail -> 当前节点相同子节点 
				q.push(t[now].son[i]);
			}
			else t[now].son[i]=t[t[now].fail].son[i];
		}
	}
}
void AC(string s){
	int l=s.length();
	int now=0,ans=0;
	rep(i,0,l-1){
		now=t[now].son[s[i]-'a'];
		for(int nw=now;nw&&t[nw].end!=-1;nw=t[nw].fail){
			ans+=t[nw].end;
			t[nw].end=-1;
		}
	}
	cout<<ans;
}
signed main(){
	n=read();
	rep(i,1,n){
		cin>>s;
		build(s);
	}
	t[0].fail=0;
	Get_fail();
	cin>>s;
	AC(s);
	return 0;
}
posted @ 2023-06-19 19:28  XYini  阅读(0)  评论(0)    收藏  举报