zoj3228
来源:互联网 发布:领航者炒股软件 编辑:程序博客网 时间:2024/06/06 01:58
这是一道很有意思的字符串的题。大部分的人都是用AC自动机过的。但是在看HH大神的博客的回复下面看到一种很有意思的解法。通常对于tire树的构造都是用字串构造。母串匹配。但是今天看到有人用母串构造tire树。但是这样构造需要一些前提。首先已经知道子串的最大的长度,其次这样的方法的构造不会MLE。开始的时候我用new node但是MLE了后来改为静态的方式构建tire就过了。我两种方法都写了一下。最开始写的是AC自动机,但是MLE了好久。最后将所有的状态hash了一下才过!!!真是!!
上代码:
(AC自动机版本)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
struct node{
node *fail;
node *next[26];
int id;
bool end;
short tag;
short len;
node(){
len=0;
id=0;
end=false;
fail=NULL;
for(int i=0;i<=25;i++){
next[i]=NULL;
}
tag=-1;
}
};
int in[100010];
int ff[100010];
const int MAXN=600010;
node* q[MAXN];
node *root=new node();
int num=1;
void insert(char word[],int flag,int k){
node *cur=root;
int i=0,branch;
while(word[i]){
branch=word[i]-'a';
if(cur->next[branch]==NULL){
cur->next[branch]=new node();
cur->next[branch]->id=num++;
}
i++;
cur=cur->next[branch];
}
in[k]=cur->id;
cur->len=strlen(word);
cur->end=true;
if(cur->tag==-1)
cur->tag=flag;
else{
if(cur->tag!=2){
if(cur->tag!=flag)
cur->tag=2;
}
}
}
void AC(){
int rear=1,front=0,i;
node *cur;
q[0]=root;
root->fail=NULL;
while(rear!=front){
cur=q[front++];
for(i=0;i<26;i++){
if(cur->next[i]!=NULL){
if(cur==root)
cur->next[i]->fail=root;
else{
node *ptr=cur->fail;
while(ptr!=NULL){
if(ptr->next[i]!=NULL){
cur->next[i]->fail=ptr->next[i];
//if(ptr->next[i]->end==true)
//cur->next[i]->end=true;
break;
}
ptr=ptr->fail;
}
if(ptr==NULL)cur->next[i]->fail=root;
}
q[rear++]=cur->next[i];
}
}
}
}
char s[100001];
char a[10];
int dp[100001][2];
int pos[100001][7];
int dpos[100001][7];
int hash[600010];
void search(){
int i=0,ans=0;
node *ptr=root;
while(s[i]){
int idx=s[i]-'a';
while(ptr->next[idx]==NULL && ptr!=root)ptr=ptr->fail;
ptr=ptr->next[idx];
if(ptr==NULL)ptr=root;
node *tmp=ptr;
while(tmp!=NULL){
if(tmp->tag==1 || tmp->tag==2){
int cnt=0; int maxx=0,maxx1=0;
for(int j=1;j<=6;j++){
if((i-pos[hash[tmp->id]][j])>=tmp->len && maxx<dpos[hash[tmp->id]][j]){
maxx=dpos[hash[tmp->id]][j];
cnt=j;
}
if((i-pos[hash[tmp->id]][j])<tmp->len && maxx1<dpos[hash[tmp->id]][j]){
maxx1=dpos[hash[tmp->id]][j];
}
}
if((maxx+1)>maxx1){
dp[hash[tmp->id]][1]=max(dp[hash[tmp->id]][1],dpos[hash[tmp->id]][cnt]+1);
if(dpos[hash[tmp->id]][6]>dpos[hash[tmp->id]][5]){
dpos[hash[tmp->id]][5]=dpos[hash[tmp->id]][6];
}
for(int j=2;j<=6;j++){
dpos[hash[tmp->id]][j]=dpos[hash[tmp->id]][j-1];
pos[hash[tmp->id]][j]=pos[hash[tmp->id]][j-1];
}
dpos[hash[tmp->id]][1]=dp[hash[tmp->id]][1];
pos[hash[tmp->id]][1]=i;
}
else
dp[hash[tmp->id]][1]=maxx1;
}
dp[hash[tmp->id]][0]++;
tmp=tmp->fail;
}
i++;
}
}
main(){
int t=1;
while(scanf("%s",s)!=-1){
int n;num=1;
root=new node();
scanf("%d",&n);
memset(hash,0,sizeof(hash));
for(int i=1;i<=n;i++){
int flag;
scanf("%d",&flag);
getchar();
scanf("%s",a);
insert(a,flag,i);
ff[i]=flag;
hash[in[i]]=i;
}
AC();
root->id=0;
memset(dp,0,sizeof(dp));
memset(pos,0,sizeof(pos));
memset(dpos,0,sizeof(dpos));
search();
printf("Case %d\n",t++);
for(int i=1;i<=n;i++){
printf("%d\n",dp[hash[in[i]]][ff[i]]);
}
printf("\n");
}
}
(tire数版本)
#include<cstdio>
#include<cstring>
using namespace std;
struct node{
int next[26];
int overlap;
int notoverlap;
int pos;
};
node ww[1000000];
int num=0;
void ini(int k){
ww[k].overlap=0;
ww[k].notoverlap=0;
ww[k].pos=-1;
for(int i=0;i<=25;i++)
ww[k].next[i]=-1;
}
void insert(char word[],int start){
int cur=0;
int i=0,branch;
while(word[i]){
branch=word[i]-'a';
if(ww[cur].next[branch]==-1){
num++;
ini(num);
ww[cur].next[branch]=num;
}
cur=ww[cur].next[branch];
ww[cur].overlap++;
if(ww[cur].pos<start){
ww[cur].notoverlap++;
ww[cur].pos=start+i;
}
i++;
}
}
char a[100010];
main(){
int t=1;
while(scanf("%s",a)!=-1){
int n;
num=0;
ini(0);
for(int i=0;a[i];i++){
char s[10];
int j=0;
for(j=0;j<=5 && a[i+j];j++){
s[j]=a[i+j];
}
s[j]=0;
insert(s,i);
}
printf("Case %d\n",t++);
scanf("%d",&n);
for(int i=0;i<=n-1;i++){
int flag,ans[2],k=0,cnt=0;
char s[10];
scanf("%d %s",&flag,s);
while(s[k]){
int branch=s[k]-'a';
if(ww[cnt].next[branch]!=-1){
cnt=ww[cnt].next[branch];
ans[0]=ww[cnt].overlap;
ans[1]=ww[cnt].notoverlap;
}
else{
break;
}
k++;
}
if(k==strlen(s)){
printf("%d\n",ans[flag]);
}
else{
printf("0\n");
}
}
printf("\n");
}
}
- zoj3228
- zoj3228
- ZOJ3228 Trie树
- ZOJ3228 Searching the String
- AC自动机zoj3228
- ZOJ3228【AC自动机】
- ZOJ3228-Searching the String
- zoj3228(AC自动机进阶)
- [ac自动机]zoj3228 Searching the String
- ZOJ3228---Searching the String(AC自动机)
- zoj3228 Searching the String AC自动机
- AC自动机 zoj3228 Searching the String
- 【ZOJ3228】白濑肆の完美算法教室补番作,0.7%达成 白濑肆×AC自动机
- delphi 操作Excel插入图片
- SSH(Secure Shell)协议简介
- HDU-1501-Zipper
- 西蒙iPhoneGL ES教程实例代码
- 华为面试题
- zoj3228
- 随笔之如何判断Android应用进程是否为单线程及闲扯多核并行编程
- log共通
- iptables执行权限
- STM32开源开发环境的搭建
- POSIX 多线程程序设计
- JSP分页技术
- OGRE 1.0 至 1.7.3 更新日志
- 日报_2012_07_22