日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

hdu3695(AC自动机)

發(fā)布時(shí)間:2025/3/15 编程问答 13 豆豆
生活随笔 收集整理的這篇文章主要介紹了 hdu3695(AC自动机) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

題意:

給出n個(gè)單詞,問又多少個(gè)在模式串中出現(xiàn)過,單詞反轉(zhuǎn)后在模式串中出現(xiàn)也算出現(xiàn)。模式串會(huì)這么給出,例如"[3A]"代表"AAA",這個(gè)數(shù)字最大會(huì)是5000000,原串的長度也是5000000,比賽的時(shí)候我就以為經(jīng)過翻譯的串會(huì)變成5000000*5000000這么長,可是賽后一看,題中說了,翻譯之后的串也不會(huì)超過5000000,真是日了狗= =,


思路:

裸的AC自動(dòng)機(jī),我最初的想法是把每個(gè)串既正著插進(jìn)字典樹,也反著插一遍,結(jié)果WA了,后來想想,果然有WA點(diǎn),這樣一個(gè)穿可能被算了兩次啊,我們可以把模式串正著跑一遍,反著再跑一遍,這樣就可以了。


代碼:

#include<iostream> #include<cstring> #include<cstdio>using namespace std;const int kind=26;//結(jié)點(diǎn)有26種,a~z struct node {node *fail;//失敗指針node *next[kind];int count;node(){fail=NULL;count=0;memset(next,NULL,sizeof(next));} }*q[5100050];//隊(duì)列用于bfs構(gòu)造失敗指針char keyword[1050];//輸入的單詞 char keyword1[1050]; char str[5100050];//模式串 int head,tail;//隊(duì)列頭和尾 char str1[5100050];void insert(char *str,node *root) {node *p=root;int i=0,index;while(str[i]){index=str[i]-'A';if(p->next[index]==NULL)p->next[index]=new node();p=p->next[index];i++;}p->count++; }void build_ac(node *root) {int i;root->fail=NULL;q[head++]=root;while(head!=tail){node *temp=q[tail++];node *p=NULL;for(int i=0;i<26;i++){if(temp->next[i]!=NULL){if(temp==root)temp->next[i]->fail=root;else{p=temp->fail;while(p!=NULL){if(p->next[i]!=NULL){temp->next[i]->fail=p->next[i];break;}p=p->fail;}if(p==NULL)temp->next[i]->fail=root;}q[head++]=temp->next[i];}}} }int query(node *root) {int i=0,cnt=0,index,len=strlen(str);node *p=root;while(str[i]){index=str[i]-'A';while(p->next[index]==NULL&&p!=root)p=p->fail;p=p->next[index];p=(p==NULL)?root:p;node *temp=p;while(temp!=root&&temp->count!=-1){cnt+=temp->count;temp->count=-1;temp=temp->fail;}i++;}return cnt; }void trans() {int j=0;int len=strlen(str1);for(int i=0;i<len;i++){if(isalpha(str1[i])) str[j++]=str1[i];else {i++;int t=0;while(isdigit(str1[i])) {t=t*10+str1[i]-'0';i++;}for(int jj = 0; jj < t; ++jj) str[j++]=str1[i];i++;}}str[j++]=0; }int main() {int t;scanf("%d",&t);while(t--){int n;head=tail=0;node *root=new node();scanf("%d",&n);getchar();while(n--){gets(keyword); // puts(keyword);insert(keyword,root);// int len=strlen(keyword);// for(int i=0,j=len-1;i<len;i++,j--)// keyword1[i]=keyword[j];// keyword1[len]=0;// insert(keyword1,root); // printf("lalalalala\n");}//printf("--------------------1\n");build_ac(root);scanf("%s",str1);//printf("%s\n",str);trans(); // printf("=================- %s\n",str1);// printf("-----------------= %s\n",str);int ans=query(root);int len=strlen(str);for(int i=0,j=len-1;i<len;i++,j--)str1[i]=str[j];for(int i=0;i<len;i++)str[i]=str1[i];ans+=query(root);printf("%d\n",ans);} }

總結(jié)

以上是生活随笔為你收集整理的hdu3695(AC自动机)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。