字符串算法模板
字符串算法都好抽象啊……
1. 字符串哈希
int hash(string s)
{
int ans=0,l=s.length();
for(int i=0;i<l;i++)ans=(ans*base%mod+(s[i]-'0'+1))%mod;
return ans;
}
2. 前缀函数
void prefix()
{
for(int i=1;i<=n-1;i++)
{
int j=pi[i-1];
while(j>0&&s[i]!=s[j])j=pi[j-1];
if(s[i]==s[j])j++;
pi[i]=j;
}
}
3. manacher
l=s.length();t+="~#";
for(int i=0;i<l;i++){t+=s[i];t+='#';}
l=2*l+2;
for(int i=1;i<l;i++)
{
if(maxr>i)r[i]=min(maxr-i,r[2*o-i]);
for(;t[i+r[i]+1]==t[i-r[i]-1];r[i]++);
if(i+r[i]>maxr){maxr=i+r[i];o=i;}
ans=max(ans,r[i]);
}
4. Trie树
void insert(string s)
{
int u=0,l=s.length();
for(int i=0;i<l;i++)
{
int now=s[i]-'a';
if(!trie[u][now])trie[u][now]=++tot;
u=trie[u][now];
}
cnt[u]++;
}
int query(string s)
{
int u=0,l=s.length();
for(int i=0;i<l;i++)
{
if(flag[u]==1)return 0;
int now=s[i]-'a';
if(!trie[u][now])return 0;
u=trie[u][now];
}
return cnt[u];
}
5. 最小表示法
int i=0,j=1,k=0;
while(i<n&&j<n&&k<n)
{
if(s[(i+k)%n]==s[(j+k)%n]){k++;continue;}
if(s[(i+k)%n]<s[(j+k)%n])j=j+k+1;
else i=i+k+1;
if(i==j)j++;
k=0;
}
ans=min(i,j);
6. Z函数
for(int i=1;i<n;i++)
{
if(r>i)z[i]=min(z[i-l],r-i+1);
for(;b[i+z[i]]==b[z[i]];z[i]++);
if(i+z[i]-1>r){l=i;r=i+z[i]-1;}
}
7. 失配树(Border树)
const int maxn=1000010;
string s;
int n,m,pi[maxn];
int cnt,h[maxn],anc[maxn][30],dep[maxn],lg2[maxn];
struct edge{int to,nxt;}e[maxn];
void addedge(int u,int v)
{
e[++cnt]=(edge){v,h[u]};
h[u]=cnt;
}
void prefix()
{
for(int i=1;i<=n-1;i++)
{
int j=pi[i-1];
while(j>0&&s[i]!=s[j])j=pi[j-1];
if(s[i]==s[j])j++;
pi[i]=j;
}
}
void dfs(int u,int fa)
{
anc[u][0]=fa;dep[u]=dep[fa]+1;
for(int i=1;i<=lg2[dep[u]];i++)anc[u][i]=anc[anc[u][i-1]][i-1];
for(int i=h[u];i;i=e[i].nxt)
{
int p=e[i].to;
if(p!=fa)dfs(p,u);
}
}
int lca(int u,int v)
{
if(dep[u]>dep[v])swap(u,v);
while(dep[u]<dep[v])v=anc[v][lg2[dep[v]-dep[u]]];
if(u==v)return u;
for(int k=lg2[dep[u]];k>=0;k--)
if(anc[u][k]!=anc[v][k])
{
u=anc[u][k];
v=anc[v][k];
}
return anc[u][0];
}
//main函数内
cin >> s >> m;n=s.length();prefix();
for(int i=1;i<=n;i++)addedge(pi[i-1],i);
for(int i=2;i<=n;i++)lg2[i]=lg2[i/2]+1;
dep[0]=-1;dfs(0,0);
for(int i=1;i<=m;i++)
{
int p,q,f;cin >> p >> q;f=lca(p,q);
if(f==p||f==q)cout << anc[f][0] << endl;
else cout << f << endl;
}
8. 子序列自动机
const int maxn=100010;
int type,n,q,m,cnt,rt[maxn],a[maxn],s[maxn];
struct node{int l,r,val;}tree[maxn*20];
void build(int &x,int l,int r)
{
x=++cnt;
if(l==r){tree[x].val=a[l];return;}
int mid=(l+r)>>1;
build(tree[x].l,l,mid);
build(tree[x].r,mid+1,r);
}
void modify(int &k,int ver,int x,int l,int r,int val)
{
k=++cnt;tree[k]=tree[ver];
if(l==r){tree[k].val=val;return;}
int mid=(l+r)>>1;
if(x<=mid)modify(tree[k].l,tree[ver].l,x,l,mid,val);
else modify(tree[k].r,tree[ver].r,x,mid+1,r,val);
}
int query(int k,int x,int l,int r)
{
if(l==r)return tree[k].val;
int mid=(l+r)>>1;
if(x<=mid)return query(tree[k].l,x,l,mid);
else return query(tree[k].r,x,mid+1,r);
}
//main函数内
for(int i=0;i<n;i++)s[i]=read();
memset(a,-1,sizeof(a));
build(rt[n],1,m);
for(int i=n-1;i>=0;i--)modify(rt[i],rt[i+1],s[i],1,m,i+1);
for(int i=1;i<=q;i++)
{
int l=read(),c,p,now=0,flag=1;
for(int j=0;j<l;j++)
{
c=read();
if(!flag)continue;
p=query(rt[now],c,1,m);
if(p==-1){flag=0;continue;}
now=p;
}
if(!flag)printf("No\n");
else printf("Yes\n");
}
9. AC自动机(ACAM)
const int maxn=200010;
int n,tot,trie[maxn][26],fail[maxn],point[maxn];
string s[maxn],t;
queue<int> q;
int cnt,h[maxn],siz[maxn];
struct edge{int to,nxt;}e[maxn];
void addedge(int u,int v)
{
e[++cnt]=(edge){v,h[u]};
h[u]=cnt;
}
void buildtrie()
{
for(int i=1;i<=n;i++)
{
int u=0,l=s[i].length();
for(int j=0;j<l;j++)
{
int now=s[i][j]-'a';
if(!trie[u][now])trie[u][now]=++tot;
u=trie[u][now];
}
point[i]=u;
}
}
void buildac()
{
for(int i=0;i<26;i++)if(trie[0][i])q.push(trie[0][i]);
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=0;i<26;i++)
if(trie[u][i])
{
fail[trie[u][i]]=trie[fail[u]][i];
q.push(trie[u][i]);
}
else trie[u][i]=trie[fail[u]][i];
}
}
void match(string ss)
{
int u=0,l=ss.length();
for(int i=0;i<l;i++)
{
u=trie[u][ss[i]-'a'];
siz[u]++;
}
}
void dfs(int u)
{
for(int i=h[u];i;i=e[i].nxt)
{
int p=e[i].to;
dfs(p);
siz[u]+=siz[p];
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin >> n;
for(int i=1;i<=n;i++)cin >> s[i];
buildtrie();
buildac();
cin >> t;match(t);
for(int i=1;i<=tot;i++)addedge(fail[i],i);
dfs(0);
for(int i=1;i<=n;i++)cout << siz[point[i]] << endl;
return 0;
}