写正文之前容我吐槽一发:HDU真坑爹啊!我在这上面交了两天不到的题什么错误都有啊!CE啊!变量名别整奇怪啊!万能库不认识啊!G++和C++不一样啊!PE啊,你最后一行给我少了个回车这是不行的啊!OLE啊!你说我手贱输出那么多值干嘛啊!卡你内存卡你初始化卡你字符串函数卡巴斯基啊!英文题面啊!ACM好厉害呀!去做个题读题时间最长啊!多组数据啊!初始化你也要想好那些需要啊!看不清楚就快滚蛋吧!地球太危险了你还是回火星吧!
传送门-P2222
题意:给一些子串和一个总串,问有多少个子串在总串中出现过
思路:AC自动机裸题,不想说什么
注意:千万别用memset!字符串取长度时先赋值到变量上!
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
int t,n,tot,root=1;
char s[53],ch[1000003];
int fail[500003],num[500003],trie[500003][26];
queue<int> q;
inline void insert(char s[])
{
int now=root,len=strlen(s);
for (int i=0;i<len;i++)
{
if (!trie[now][s[i]-'a']) trie[now][s[i]-'a']=++tot;
now=trie[now][s[i]-'a'];
}
num[now]++;
}
inline void build()
{
int now=root;
q.push(root);
while (!q.empty())
{
now=q.front();
q.pop();
for (int i=0;i<26;i++)
if (trie[now][i])
{
int tmp=fail[now];
while (!trie[tmp][i]&&tmp) tmp=fail[tmp];
if (now!=root&&tmp)fail[trie[now][i]]=trie[tmp][i];
else fail[trie[now][i]]=root;
q.push(trie[now][i]);
}
}
}
int main()
{
scanf("%d",&t);
while (t--)
{
tot=1;
scanf("%d",&n);
while (n--)
{
scanf("%s",s);
insert(s);
}
build();
scanf("%s",ch);
int now=root,ans=0,len=strlen(ch);
for (int i=0;i<len;i++)
{
while (!trie[now][ch[i]-'a']&&now) now=fail[now];
if (!now) now=root;
else now=trie[now][ch[i]-'a'];
int tmp=now;
while (tmp!=root)
{
ans+=num[tmp];
num[tmp]=0;
tmp=fail[tmp];
}
}
printf("%d\n",ans);
for (int i=1;i<=tot;i++)
{
num[i]=fail[i]=0;
for (int j=0;j<26;j++) trie[i][j]=0;
}
}
}
传送门-P2896
题意:是中文题面终于不用找翻译了哈哈
思路:记录编号与总数
注意:依旧卡内存,把你能想象到的技巧全用上吧!(为什么ASCLL不是0-255呢……)
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
int n,m,tot=1,root=1,ans;
int trie[100010][128],fail[100010],num[100010];
char s[10010];
bool flag[510];
queue <int> q;
void insert(int x,char s[])
{
int len=strlen(s),now=root;
for (int i=0;i<len;i++)
{
if (!trie[now][s[i]]) trie[now][s[i]]=++tot;
now=trie[now][s[i]];
}
num[now]=x;
}
void build()
{
int now=root,tmp;
q.push(now);
while (!q.empty())
{
now=q.front();
q.pop();
for (int i=0;i<=127;i++)
if (trie[now][i])
{
tmp=fail[now];
while (tmp&&!trie[tmp][i]) tmp=fail[tmp];
if (now!=root&&tmp) fail[trie[now][i]]=trie[tmp][i];
else fail[trie[now][i]]=root;
q.push(trie[now][i]);
}
}
}
bool solve(int x)
{
scanf("%s",s);
int tmp,len=strlen(s),now=root,cnt=0;
memset(flag,0,sizeof(flag));
for (int i=0;i<len;i++)
{
while (now&&!trie[now][s[i]]) now=fail[now];
if (!now) now=root;
else now=trie[now][s[i]];
tmp=now;
while (tmp!=root)
{
if (num[tmp]) cnt++,flag[num[tmp]]=1;
tmp=fail[tmp];
}
}
if (!cnt) return 0;
printf("web %d:",x);
for (int i=1;i<=n;i++)
if (flag[i]) printf(" %d",i);
puts("");
return 1;
}
main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%s",s),
insert(i,s);
build();
scanf("%d",&m);
for (int i=1;i<=m;i++)
if (solve(i)) ans++;
printf("total: %d\n",ans);
}
传送门-P3065
题意:中文
思路:基本与上面相同,当主串中当前位置不是大写字母时可以直接跳回root
注意:多组数据!多组数据!题面中没说,但是多组数据!
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#define pd(i) (i>='A'&&i<='Z')
using namespace std;
int n,root=1,tot=1;
char ch[1002][52],s[2000002];
int ans[50010],num[50010],fail[50010],trie[50010][26];
queue <int> q;
void insert(int x,char s[])
{
int now=root,len=strlen(s);
for (int i=0;i<len;i++)
{
if (!trie[now][s[i]-'A']) trie[now][s[i]-'A']=++tot;
now=trie[now][s[i]-'A'];
}
num[now]=x;
}
void build()
{
int now=root,tmp;
q.push(now);
while (!q.empty())
{
now=q.front();
q.pop();
for (int i=0;i<26;i++)
if (trie[now][i])
{
tmp=fail[now];
while (tmp&&!trie[tmp][i]) tmp=fail[tmp];
if (now!=root&&tmp) fail[trie[now][i]]=trie[tmp][i];
else fail[trie[now][i]]=root;
q.push(trie[now][i]);
}
}
}
void work()
{
tot=1;
memset(ans,0,sizeof(ans));
memset(trie,0,sizeof(trie));
memset(num,0,sizeof(num));
for (int i=1;i<=n;i++)
scanf("%s",ch[i]),
insert(i,ch[i]);
build();
scanf("%s",s);
int now=root,tmp,len=strlen(s);
for (int i=0;i<len;i++)
{
if (!pd(s[i])) {now=root;continue;}
while (now&&!trie[now][s[i]-'A']) now=fail[now];
if (!now) now=root;
else now=trie[now][s[i]-'A'];
tmp=now;
while (tmp!=root)
{
if (num[tmp]) ans[num[tmp]]++;
tmp=fail[tmp];
}
}
for (int i=1;i<=n;i++)
if (ans[i])
printf("%s: %d\n",ch[i],ans[i]);
}
main()
{
while (scanf("%d",&n)!=EOF)
work();
}
本来还想再放一道ZOJ上的题,但是它交不上!不是CE、RE,而是真的交不上!一交就出错!弃疗的我打了个A+B上用这个问题交了上去却能交上!!!