20190816
字符串匹配
哈希函数
字典树
kmp
https://www.cnblogs.com/ZuoAndFutureGirl/p/9028287.html
#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std ;
const int maxn = 1e6+5;
int Next[maxn];
int T[maxn];
int S[maxn];
int n1,n2;
void GetNextval()
{
int k = -1;
int j = 0;
while (j < n2-1)
{
if (k == -1 || T[j] == T[k])
{
++j;
++k;
if (T[j] != T[k])
Next[j] = k;
else
Next[j] = Next[k];
}
else
{
k = Next[k];
}
}
}
int kmp()
{
Next[0] = -1;
GetNextval();
int cnt=0;
int i=0,j=0;
while(i<n1&&j<n2)
{
if(j==-1||S[i]==T[j]) i++,j++;
else j=Next[j];
}
if(j==n2)
return i-n2+1;
else
return -1;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin>>t;
while(t--)
{
cin>>n1>>n2;
for(int i=0;i<n1;i++) cin>>S[i];
for(int j=0;j<n2;j++) cin>>T[j];
cout<<kmp()<<endl;
}
return 0;
}
AC自动机算法
https://www.cnblogs.com/cmmdc/p/7337611.html
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<string>
#include<sstream>
#define mst(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn=1e6+5;
typedef long long LL;
int n,m,t;
int tire[maxn][26];
int num[maxn];
int pos=0;
int cnt; //统计字符串的个数
char sk[maxn]; //模式串
char ssk[maxn]; //目标串
int vis[maxn]; //统计字符串是否出现
int wordnum[maxn]; //统计字符串出现次数-用数组
int fail[maxn]; //失败指针
int last[maxn]; //表示沿着失配指针走遇到的第一个单词节点的编号
void buildTree(char s[])
{
int p=0;
int len=strlen(s);
for(int i=0;i<len;i++){
int j=s[i]-'a';
if(!tire[p][j])
{
tire[p][j]=++pos;
wordnum[pos]=0;
mst(tire[pos],0);
}
p=tire[p][j];
num[p]++;
}
if(!vis[p])
++cnt;
vis[p]=1;
wordnum[p]++;
}
void get_Fail()
{
queue<int> q;
fail[0]=0;
int u=0;
for(int i=0;i<26;i++)
{
u=tire[0][i];
if(u){q.push(u);fail[u]=0;last[u]=0;}
}
while(!q.empty())
{
int r=q.front();q.pop();
for(int i=0;i<26;i++)
{
u=tire[r][i];
if(!u){tire[r][i]=tire[fail[r]][i];continue;}
q.push(u);
int v=fail[r];
while(v&&!tire[v][i])v=fail[v];
fail[u]=tire[v][i];
last[u]=wordnum[fail[u]]?fail[u]:last[fail[u]];
}
}
}
/**查询*/
int query(char *str)
{
int u=0,ans=0;
int n=strlen(str);
for(int i=0;i<n;i++)
{
int c=str[i]-'a';
u=tire[u][c];
int temp=0;//必须赋初值为0,表示如果下面两个判断都不成立的时候while可以正常执行
if(wordnum[u])
temp=u;
else if(last[u])
temp=last[u];
while(temp)
{
ans+=wordnum[temp];
wordnum[temp]=0;
temp=last[temp];
}
}
return ans;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>t;
while(t--)
{
mst(tire,0);
mst(wordnum,0);
cin>>n;
for(int i=0;i<n;i++)
{
cin>>sk;
buildTree(sk);
}
get_Fail();
cin>>ssk;
int res=query(ssk);
cout<<res<<endl;
}
return 0;
}