大三了,在网络赛结束那刻决定放弃搞算法了,做了一个的安卓,却被告知暑假参加的ACM网络赛北京赛区成功进入现场赛,意外又惊喜,感觉付出都不是白费的,然后又滚回去刷题了,整理了一些模板,跟你们分享:
ac自动机
模型:我们给出5个单词,say,she,shr,he,her。给定字符串为yasherhs。问多少个单词在字符串中出现过。
模板:
//======================
// HDU 2222
// 求目标串中出现了几个模式串
//====================
#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <string.h>
#include <queue>
using namespace std;
struct Trie
{
int next[500010][26],fail[500010],End[500010];
int root,L;
int newnode()
{
for(int i = 0;i < 26;i++)
next[L][i] = -1;
End[L++] = 0;
return L-1;
}
void init()
{
L = 0;
root = newnode();
}
void Insert(char buf[])
{
int len = strlen(buf);
int now = root;
for(int i = 0;i < len;i++)
{
if(next[now][buf[i]-'a'] == -1)
next[now][buf[i]-'a'] = newnode();
now = next[now][buf[i]-'a'];
}
End[now]++;
}
void build()
{
queue<int>Q;
fail[root] = root;
for(int i = 0;i < 26;i++)
if(next[root][i] == -1)
next[root][i] = root;
else
{
fail[next[root][i]] = root;
Q.push(next[root][i]);
}
while( !Q.empty() )
{
int now = Q.front();
Q.pop();
for(int i = 0;i < 26;i++)
if(next[now][i] == -1)
next[now][i] = next[fail[now]][i];
else
{
fail[next[now][i]]=next[fail[now]][i];
Q.push(next[now][i]);
}
}
}
int query(char buf[])//查询该串出现多少个模式串;
{
int len = strlen(buf);
int now = root;
int res = 0;
for(int i = 0;i < len;i++)
{
now = next[now][buf[i]-'a'];
int temp = now;
while( temp != root )
{
res += End[temp];
End[temp] = 0;
temp = fail[temp];
}
}
return res;
}
void debug()
{
for(int i = 0;i < L;i++)
{
printf("id = %3d,fail = %3d,end = %3d,chi = [",i,fail[i],End[i]);
for(int j = 0;j < 26;j++)
printf("%2d",next[i][j]);
printf("]\n");
}
}
};
char buf[1000010];
Trie ac;
int main()
{
int T;
int n;
scanf("%d",&T);
while( T-- )
{
scanf("%d",&n);
ac.init();
for(int i = 0;i < n;i++)
{
scanf("%s",buf);//模式串
ac.Insert(buf);
}
ac.build();
scanf("%s",buf);//主串
printf("%d\n",ac.query(buf));
}
return 0;
}
hdu2296
题目:给出m个模式串,每个串有一定的分值,构造一个长度不超过n的串,使得分值最大,输出长度最小,字典序最小的串
明显的AC+DP,dp[i][j]表示长度为i的时候,在Trie上的第j个结点时的最大分值,path[i][j]表示状态(i,j)时的字典序最小的串。
当最大值为0的时候,输出的是空串,
include<iostream>
include<cstdio>
include<map>
include<cstring>
include<cmath>
include<vector>
include<algorithm>
include<set>
include<string>
include<queue>
define inf 1<<30
define M 60005
define N 10005
define maxn 300005
define eps 1e-10
define zero(a) fabs(a)<eps
define Min(a,b) ((a)<(b)?(a):(b))
define Max(a,b) ((a)>(b)?(a):(b))
define pb(a) push_back(a)
define mem(a,b) memset(a,b,sizeof(a))
define LL long long
define lson step<<1
define rson step<<1|1
using namespace std;
struct Trie
{
Trie *next[26];
Trie *fail;
int isword,kind;
};
Trie *que[M],s[M];
int dp[55][N],idx;
int n,m,h[105];
char str[105][105];
string path[55][N];
Trie *NewNode()
{
Trie *tmp=&s[idx];
mem(tmp->next,NULL);
tmp->isword=0;
tmp->fail=NULL;
tmp->kind=idx++;
return tmp;
}
void Insert(Trie *root,char *s,int len,int k)
{
Trie *p=root;
for(int i=0; i<len; i++)
{
if(p->next[s[i]-'a']==NULL) p->next[s[i]-'a']=NewNode();
p=p->next[s[i]-'a'];
}
p->isword=h[k];
}
void Bulid_fail(Trie *root)
{
int head=0,tail=0;
que[tail++]=root;
root->fail=NULL;
while(head<tail)
{
Trie *tmp=que[head++];
for(int i=0; i<26; i++)
{
if(tmp->next[i])
{
if(tmp==root) tmp->next[i]->fail=root;
else
{
Trie *p=tmp->fail;
while(p!=NULL)
{
if(p->next[i])
{
tmp->next[i]->fail=p->next[i];
break;
}
p=p->fail;
}
if(p==NULL) tmp->next[i]->fail=root;
}
if(tmp->next[i]->fail->isword) tmp->next[i]->isword+=tmp->next[i]->fail->isword;
que[tail++]=tmp->next[i];
}
else if(tmp==root) tmp->next[i]=root;
else tmp->next[i]=tmp->fail->next[i];
}
}
}
void slove()
{
int ans=0;
mem(dp,-1);
dp[0][0]=0;
for(int i=0;i<=n;i++) for(int j=0;j<idx;j++) path[i][j].clear();
for(int i=0;i<n;i++)
{
for(int j=0;j<idx;j++)
{
if(dp[i][j]==-1) continue;
for(int k=0;k<26;k++)
{
int cur=s[j].next[k]->kind;
if(dp[i][j]+s[cur].isword>dp[i+1][cur])
{
dp[i+1][cur]=dp[i][j]+s[cur].isword;
path[i+1][cur]=path[i][j]+(char)(k+'a');
}
else if(dp[i][j]+s[cur].isword==dp[i+1][cur]&&path[i][j]+(char)(k+'a')<path[i+1][cur])
{
path[i+1][cur]=path[i][j]+(char)(k+'a');
}
}
}
}
for(int i=1;i<=n;i++) for(int j=0;j<idx;j++) ans=max(ans,dp[i][j]);
if(ans==0) {puts("");return;}
string str=" ";
for(int i=1;i<=n;i++) for(int j=0;j<idx;j++) if(dp[i][j]==ans&&(str==" "||(path[i][j].size()<str.size()||(path[i][j].size()==str.size()&&path[i][j]<str)))) str=path[i][j];
cout<<str<<endl;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
idx=0;
Trie *root=NewNode();
scanf("%d%d",&n,&m);
for(int i=1; i<=m; i++)
scanf("%s",str[i]);
for(int i=1;i<=m;i++)
{
scanf("%d",&h[i]);
Insert(root,str[i],strlen(str[i]),i);
}
Bulid_fail(root);
slove();
}
return 0;
}
hdu2986病毒侵袭
要输出出现模式串的id,用end记录id就可以了。还有trie树的分支是128的
//============================================================================
// Name : HDU.cpp
// Author :
// Version :
// Copyright : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================
include <stdio.h>
include <string.h>
include <iostream>
include <algorithm>
include <queue>
using namespace std;
struct Trie
{
int next[210*500][128],fail[210*500],end[210*500];
int root,L;
int newnode()
{
for(int i = 0;i < 128;i++)
next[L][i] = -1;
end[L++] = -1;
return L-1;
}
void init()
{
L = 0;
root = newnode();
}
void insert(char s[],int id)
{
int len = strlen(s);
int now = root;
for(int i = 0;i < len;i++)
{
if(next[now][s[i]] == -1)
next[now][s[i]] = newnode();
now=next[now][s[i]];
}
end[now]=id;
}
void build()
{
queue<int>Q;
fail[root] = root;
for(int i = 0;i < 128;i++)
if(next[root][i] == -1)
next[root][i] = root;
else
{
fail[next[root][i]] = root;
Q.push(next[root][i]);
}
while(!Q.empty())
{
int now = Q.front();
Q.pop();
for(int i = 0;i < 128;i++)
if(next[now][i] == -1)
next[now][i] = next[fail[now]][i];
else
{
fail[next[now][i]] = next[fail[now]][i];
Q.push(next[now][i]);
}
}
}
bool used[510];
bool query(char buf[],int n,int id)
{
int len = strlen(buf);
int now = root;
memset(used,false,sizeof(used));
bool flag = false;
for(int i = 0;i < len;i++)
{
now = next[now][buf[i]];
int temp = now;
while(temp != root)
{
if(end[temp] != -1)
{
used[end[temp]] = true;
flag = true;
}
temp = fail[temp];
}
}
if(!flag)return false;
printf("web %d:",id);
for(int i = 1;i <= n;i++)
if(used[i])
printf(" %d",i);
printf("\n");
return true;
}
};
char buf[10010];
Trie ac;
int main()
{
int n,m;
while(scanf("%d",&n) != EOF)
{
ac.init();
for(int i = 1;i <= n;i++)
{
scanf("%s",buf);
ac.insert(buf,i);
}
ac.build();
int ans = 0;
scanf("%d",&m);
for(int i = 1;i <= m;i++)
{
scanf("%s",buf);
if(ac.query(buf,n,i))
ans++;
}
printf("total: %d\n",ans);
}
return 0;
}