BZOJ3172: [Tjoi2013]單詞

【傳送門:BZOJ3172】


簡要題意:

  給出n個單詞,你可以理解為將這些單詞變成一個個段落,然后求出每個單詞在所有段落中出現的次數


題解(一):

  剛開始不是很懂題目,結果發現將所有單詞看成一篇文章,每個單詞看成一個段落就懂了

  由于某種unbelievable的原因,我剛好做了AC自動機的專題訓練,看到這道題就秒想AC自動機

  將每個單詞放進AC自動機里,每個點的s表示有多少個單詞經過,然后在構建失敗指針的時候,通過隊列來更新s值,怎么更新呢,假設有一個i點,它的失敗指針指向j,設sj為從根到j點所構成的字符串,si為從根到i點所構成的字符串,那么我們可以知道sj為si的后綴,也說明了si中有sj的出現,那么就將j點的s值加上i點的s值,達到更新且不重復的目的來求出答案


?

參考代碼(一):

#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
using namespace std;
struct node
{int s,c[27],fail;node(){s=fail=0;memset(c,-1,sizeof(c));}
}t[1100000];
int tot,ans,n;
char a[1100000];
int ed[210];
void bt(int k,int root)
{int x=root,len=strlen(a+1);for(int i=1;i<=len;i++){int y=a[i]-'a'+1;if(t[x].c[y]==-1){t[x].c[y]=++tot;}x=t[x].c[y];t[x].s++;}ed[k]=x;
}
int list[1100000];
void bfs()
{int x;int head=1,tail=1;list[1]=0;while(head<=tail){x=list[head];for(int i=1;i<=26;i++){int son=t[x].c[i];if(son==-1)continue;if(x==0) t[son].fail=0;else{int j=t[x].fail;while(j!=0&&t[j].c[i]==-1) j=t[j].fail;t[son].fail=max(t[j].c[i],0);int x=t[son].fail,y=son;}list[++tail]=son;}head++;}for(int i=tail;i>=1;i--) t[t[list[i]].fail].s+=t[list[i]].s;
}
int main()
{ans=tot=0;scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%s",a+1);bt(i,0);}bfs();for(int i=1;i<=n;i++){printf("%d\n",t[ed[i]].s);}return 0;
}

?


?

題解(二):

   ?A了這道題之后才發現早在之前就A了(心酸)

  那我們就來搞一下第二種想法

  很容易就想到AC自動機,但是單單是AC自動機還不行

  這時就要用AC自動機的延伸——fail樹來做(時常膜一膜算法,有益身體健康)

  fail樹這個玩意就是將AC自動機中fail指針當成是一條邊,然后建成一棵樹

  由于trie樹上的每個點相當于一個字符串,所以這棵fail樹父親節點是兒子節點所構成字符串的最長后綴

  這樣子對于這道題而言,fail樹簡直就是神一般的存在QAQ

  首先將每個字符串放進trie樹里面,并且每經過一個trie樹里的點,就用s數組記錄這個字符串出現的個數,每經過一次就加一,然后構造AC自動機,然后在構造AC自動機的過程中,對每個點的fail指針進行建邊,然后用dfs從根往下遍歷,把s數組從下往上累加

  然后在輸入每個字符串的時候,記錄每個字符串的最后一個字符在trie樹上的編號,然后一個一個輸出s[end[i]](end[i]表示第i個字符串最后一個字母在trie樹上的編號)


參考代碼(二):

#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
using namespace std;
struct node
{int c[27],fail;node(){fail=0;memset(c,-1,sizeof(c));}
}t[1100000];
int tot,n;
char st[1100000];
int s[1100000];
int end[1100000];
void bt(int root,int z)
{int x=root,len=strlen(st+1);for(int i=1;i<=len;i++){int y=st[i]-'a'+1;if(t[x].c[y]==-1){t[x].c[y]=++tot;}x=t[x].c[y];s[x]++;}end[z]=x;
}
struct edge
{int x,y,next;
}a[1100000];int len,last[1100000];
void ins(int x,int y)
{len++;a[len].x=x;a[len].y=y;a[len].next=last[x];last[x]=len;
}
queue<int> q;
void bfs()
{int x;q.push(0);while(q.empty()==0){x=q.front();for(int i=1;i<=26;i++){int son=t[x].c[i];if(son==-1)continue;if(x==0) t[son].fail=0;else{int j=t[x].fail;while(j!=0&&t[j].c[i]==-1) j=t[j].fail;t[son].fail=max(t[j].c[i],0);}ins(t[son].fail,son);q.push(son);}q.pop();}
}
void dfs(int x)
{for(int k=last[x];k;k=a[k].next){int y=a[k].y;dfs(y);s[x]+=s[y];}
}
int main()
{tot=0;scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%s",st+1);bt(0,i);}len=0;memset(last,0,sizeof(last));bfs();dfs(0);for(int i=1;i<=n;i++) printf("%d\n",s[end[i]]);return 0;
}

?

?

轉載于:https://www.cnblogs.com/Never-mind/p/7628734.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/282232.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/282232.shtml
英文地址,請注明出處:http://en.pswp.cn/news/282232.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

MySQL5.6二進制軟件包編譯安裝詳解(三)

一、軟件環境 [rootlocalhost ~]# uname -r 3.10.0-862.el7.x86_64 [rootlocalhost ~]# cat /etc/redhat-release CentOS Linux release 7.5.1804 (Core) 二、安裝部署過程詳解 MySQL安裝3種方式&#xff1a;1>rpm包安裝應用文件默認安裝在/usr/local 目錄下2>源碼編譯需…

Java反射學習總結五(Annotation(注解)-基礎篇)

Annotation(注解)簡單介紹&#xff1a; 注解大家印象最深刻的可能就是JUnit做單元測試,和各種框架里的使用了。本文主要簡介一下注解的用法&#xff0c;下篇文章再深入的研究。 annotation并不直接影響代碼語義。可是它可以被看作類似程序的工具或者類庫。它會反過來對正在執行…

使用autok3s 安裝k3s 集群 和 kuboard 管理集群

一、k3s介紹1.1 什么是k3s?k3s 是經過 CNCF 認證的由 Rancher 公司開發維護的一個輕量級的 Kubernetes 發行版&#xff0c;內核機制還是和 k8s 一樣&#xff0c;但是剔除了很多外部依賴以及 K8s 的 alpha、beta 特性&#xff0c;同時改變了部署方式和運行方式&#xff0c;目的…

Nginx—— Rewrite規則的使用

一、使用場景 1、URL訪問跳轉 &#xff08;1&#xff09;頁面跳轉 &#xff08;2&#xff09;兼容性支持&#xff08;比如新老版本交替時&#xff0c;給老版本一條訪問道路&#xff09; &#xff08;3&#xff09;展示效果&#xff08;比如縮短前臺界面的地址欄的url&#…

java對象實例化的方式

java對象實例化的方式有以下幾種&#xff1a;1、使用new2、工廠模式3、反射4、clone()方法5、反序列化方式 /** 實現Cloneable和Serializable接口 */public class Book implements Cloneable, Serializable {private static final long serialVersionUID 1L; private Integer …

iOS-生成二維碼圖片【附中間帶有小圖標二維碼】(QRCode)

生成二維碼圖片也是項目中常用到的&#xff0c;二維碼的掃描Git上有很多好用的&#xff0c;這里主要說下二維碼的生成 1.普通二維碼 方法 /**生成二維碼QRStering&#xff1a;字符串imageFloat&#xff1a;二維碼圖片大小*/ (UIImage *)createQRCodeWithString:(NSString *)QRS…

libubox

lbubox是openwrt的一個核心庫&#xff0c;封裝了一系列基礎實用功能&#xff0c;主要提供事件循環&#xff0c;二進制格式處理&#xff0c;linux鏈表實現和一些JSON輔助處理。 它的目的是以動態鏈接庫方式來提供可重用的通用功能&#xff0c;給其他模塊提供便利和避免再造輪子。…

社區糾紛不斷:程序員何苦為難程序員

出品 | OSC開源社區&#xff08;ID&#xff1a;oschina2013)今年年初&#xff0c;我們報道“因為被多人侮辱大吼&#xff0c;Swift 之父正式退出 Swift 核心團隊”。諸如此類的“語言暴力”、“網絡暴力”事件在開源社區乃至整個 IT 社區屢見不鮮。多個技術社區&#xff0c;都出…

PHP 分布式集群中session共享問題以及session有效期的設置

一、Session的原理 以下以默認情況舉例&#xff1a; session_start();之后&#xff0c;會生成一個唯一的session_id&#xff0c;每一個用戶對應唯一一個session_id&#xff0c;每一個session_id對應服務器端的一個session文件。這個session文件存儲著當前session_id的信息&am…

[SDOI2009]Bill的挑戰——全網唯一 一篇容斥題解

全網唯一一篇容斥題解 Description Solution 看到這個題&#xff0c;大部分人想的是狀壓dp 但是我是個蒟蒻沒想到&#xff0c;就用容斥切掉了。 并且復雜度比一般狀壓低&#xff0c; &#xff08;其實這個容斥的算法&#xff0c;提出來源于ywy_c_asm&#xff09; &#xff08;然…

[NOIP2015提高組]運輸計劃

題目&#xff1a;BZOJ4326、洛谷P2680、Vijos P1983、UOJ#150、codevs4632、codevs5440。 題目大意&#xff1a;有一棵帶權樹&#xff0c;有一些運輸計劃&#xff0c;第i個運輸計劃從ai到bi&#xff0c;耗時為ai到bi的距離&#xff0c;所有運輸計劃一起開始。現在可以把一條邊權…

對象存儲OSS服務

一、oss是什么 阿里云對象存儲服務&#xff08;Object Storage Service&#xff0c;簡稱OSS&#xff09;為您提供基于網絡的數據存取服務。使用OSS&#xff0c;您可以通過網絡隨時存儲和調用包括文本、圖片、音頻和視頻等在內的各種非結構化數據文件。 阿里云OSS將數據文件以…

《Access 2007開發指南(修訂版)》一一1.5 什么是數據庫對象

本節書摘來自異步社區出版社《Access 2007開發指南(修訂版)》一書中的第1章&#xff0c;第1.5節&#xff0c;作者&#xff1a; 【美】Alison Balter&#xff0c;更多章節內容可以訪問云棲社區“異步社區”公眾號查看。 1.5 什么是數據庫對象 Access 2007開發指南(修訂版)正如前…

ETL工具kettle的組件--生成記錄

今天介紹下kettle的一個比較實用的組件——生成記錄&#xff1b;當我們想將一部分文本數據變成數據行&#xff0c;每個字段作為一個數據行的一個列&#xff0c;那么我們可以利用這個組件&#xff1b;它的位置在雙擊點開根據自己的實際需要進行設置當設置后&#xff0c;可以點擊…

Linux學習筆記一

linux  kernel lib module shell tools ls -la&#xff1a; 顯示所有文件包括隱藏文件  cat /proc/cpuinfo&#xff1a; 顯示cpu信息 man man  /string&#xff1a; 向上搜索string字符串 繼續按下小寫n向上搜索  ?string&#xff1a; 向下搜索string字符串 繼續按下大…

PHP中路由和rewrite的使用

一、場景介紹&#xff1a; 1、簡化url地址&#xff0c;方便大家記憶 2、有利于搜索引擎優化 3、安全&#xff08;讓用戶看不出網站的目錄結構&#xff09; 舉例&#xff1a;比如我這里將main控制器中的bb方法路由到kk&#xff0c;這樣&#xff0c;我們a標簽請求跳轉到cp.xi…

《NoSQL權威指南》導讀

引言 NoSQL權威指南“沒有什么會比引入新秩序更難&#xff0c;因為創新者必須要面對那些在舊環境中已經做得很好的對手&#xff0c;以及那些在新環境中做得很好的冷漠者。” ——Niccolo Machiavelli [1] 在過去的幾十年&#xff0c;我已經通過Elsevier/Morgan Kaufmann出版社出…

zookeeper的單實例和偽集群部署

原文鏈接: http://gudaoyufu.com/?p1395 zookeeper工作方式 ZooKeeper 是一個開源的分布式協調服務&#xff0c;由雅虎創建&#xff0c;是 Google Chubby 的開源實現。 分布式應用程序可以基于 ZooKeeper 實現諸如數據發布/訂閱、負載均衡、命名服務、分布式協 調/通知、集群管…

PHP開發常見功能實現流程

一、pc端網站登錄 1、獲取并過濾用戶提交的用戶名和密碼以及驗證碼 2、驗證用戶提交驗證碼和session中的驗證碼是否一致 3、驗證用戶名是否存在 4、根據用戶名獲取密碼&#xff0c;并校驗密碼是否一致 5、密碼一致&#xff0c;則登錄成功&#xff0c;跳轉到對應的首頁 圖示…

七牛直播云服務技術揭秘

以下根據七牛云首席布道師何李石現場演講內容整理。 直播模型及其實現 一個通用的直播模型一般包括三個模塊&#xff1a;主播方、服務器端和播放端。 首先是主播方&#xff0c;它是產生視頻流的源頭&#xff0c;由一系列流程組成&#xff1a; 第一&#xff0c;通過一定的設備來…