您的位置:首页 > 其它

【ZOJ3228】白濑肆の完美算法教室补番作,0.7%达成 白濑肆×AC自动机

2012-08-20 01:51 429 查看
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <queue>

using namespace std;

/**
就是一个AC自动机
但是每个单词有两个状态,[0]是可以overlap,[1]是不能overlap时候的次数
我们用last数组记录下每个不能overlap的单词出现的位置,如果
当前位置 - last[word] + 1 > strlen(word),那么证明该单词并未overlap,更新last数组,对应次数+1即可
补番作,水题。
*/
const int MAX_ALPHABET = 27;
const int MAX_TEXT = 100010;
const int MAX_WORD = 7;
const int MAX_WORD_NUM = 100010;
struct node
{
int id;
int cnt;
int len;
node* fail;
node* next[MAX_ALPHABET];
node()
{
id = -1; //指定该单词出现的位置。
cnt = 0;
fail = NULL;
len = 0;
memset(next,0,sizeof(next));
}
};
int cnt;
int loc[MAX_WORD_NUM];
int type[MAX_WORD_NUM];
int strcnt[MAX_WORD_NUM][2]; // 每个词儿两个状态
int last[MAX_WORD_NUM]; //每个词最后一次出现的地方。
queue<node*> q;
////变量区结束///
int AC_insert(node* root,char* dest,int flag)
{
node* tmp = root;
int l = strlen(dest);
for(int i = 0 ; i < l ; i++)
{
int k = dest[i]-'a';
if( tmp->next[k] == NULL )
{
tmp->next[k] = new node();
}
tmp = tmp->next[k];
}
if( tmp->id == -1)
{
tmp->id = cnt;
cnt++;
}
tmp->cnt = tmp->cnt | flag;
tmp->len = l;
return tmp->id;  //标明该单词在单词列表中第几个出现。。。
}
void AC_build(node* root)
{
root->fail = NULL;
q.push(root);
while(!q.empty())
{
node* tmp = q.front();
q.pop();
node *p;
for(int i = 0 ; i < 26 ; i++)
{
if(tmp->next[i])
{
if( tmp == root )
{
tmp->next[i]->fail = root;
}
else
{
p = tmp->fail;
while(p)
{
if( p->next[i] )
{
tmp->next[i]->fail = p->next[i];
break;
}
p = p->fail;
}
if( !p )
tmp->next[i]->fail = root;
}
q.push(tmp->next[i]);
}
}
}
}
void AC_search(node* root,char* dest)
{
node* tmp;
node* p;
p = root;
for(int i = 0 ; dest[i] ; i++)
{
int ind = dest[i] - 'a';
while( p->next[ind]==NULL && p != root)
p = p->fail;
p = p->next[ind];
if( p == NULL )
p = root;
tmp = p;
while( tmp != NULL )
{
if( tmp->id != -1 )
{
if( tmp->cnt & 1 )
{
strcnt[tmp->id][0]++;
}
if( tmp->cnt & 2 )
{
if( i - tmp->len + 1 > last[tmp->id] )
{
strcnt[tmp->id][1]++;
last[tmp->id] = i;
}
}
}
tmp = tmp->fail;
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("B:\\acm\\SummerVacation\\String-I\\B.in","r",stdin);
freopen("B:\\acm\\SummerVacation\\String-I\\B.out","w",stdout);
#endif
char dest[MAX_TEXT];
char word[MAX_WORD];
int t = 1;
while(scanf("%s",dest) != EOF)
{
memset(last,-1,sizeof(last));
memset(strcnt,0,sizeof(strcnt));
cnt = 1;
node* root = new node();

int N;
scanf("%d",&N);
for(int i = 0 ; i < N ; i++)
{
scanf("%d %s",&type[i],word);
loc[i] = AC_insert(root,word,type[i]+1);
}
AC_build(root);
AC_search(root,dest);
printf("Case %d\n",t++);
int ans;
for(int i = 0 ; i < N ; i++)
{
ans = strcnt[loc[i]][type[i]];
printf("%d\n",ans);
}
printf("\n");
}
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return 0;
}



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: