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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

KMP Trie 例题讲解

發布時間:2023/12/3 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 KMP Trie 例题讲解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

    • HDU 4763 Theme Section
      • 題意:
      • 題解:
      • 代碼:
    • POJ 3630 Phone List
      • 題意:
      • 題解:
      • 代碼:
    • HDU 3746 Cyclic Nacklace
      • 題意:
      • 題解:
      • 代碼:
    • HDU 2087 剪花布條
      • 題意:
      • 題解:
      • 代碼:
    • HDU 1251 統計難題
      • 題意:
      • 題解:
      • 代碼:
    • HDU 2072 單詞數
      • 題意:
      • 題解:
      • 代碼:
    • POJ 2513 Colored Sticks
      • 題意:
      • 題解:
      • 代碼:

HDU 4763 Theme Section

題意:

題解:

代碼:

POJ 3630 Phone List

題意:

n個號碼,如果有一個號碼是其他號碼的前綴,則輸出NO,否則輸出YES

題解:

根據字典序排序,然后判斷相鄰的兩個字典序是否有前綴

代碼:

#include<iostream> #include<cstdio> #include<string> #include<algorithm> using namespace std; char s[30]; string w[100005]; int main() {int T,n;bool F=0;scanf("%d",&T);while(T--){scanf("%d",&n);F=0;//memset(w,0,sizeof(w));for(int i=0;i<n;i++)cin>>w[i];sort(w,w+n);for(int i=1;i<n;i++){if(w[i].length()>w[i-1].length()){int j;for(j=0;j<w[i-1].size();j++)if(w[i][j]!=w[i-1][j])break;if(j==w[i-1].size())F=1; }}if(F) cout<<"NO"<<endl;else cout<<"YES"<<endl;}}

靜態數組寫字典樹做法:

#include <cstdlib> #include <cstdio> #include <cstring> typedef struct node //節點的結構體 {bool end;//結束的標志int a[10]; }node; node phonelist[100000]; int x; int flag; void Init() {flag=1;//標志x=0; //初始位置;for(int i=0;i<100000;i++){phonelist[i].end=false;for(int j=0;j<10;j++)phonelist[i].a[j]=-1;} } int build(char *s) //建立字典樹 {int k,now=0,tag=0;// 初始位置int len=strlen(s);for(int i=0;i<len;i++){k=s[i]-'0';if(phonelist[now].a[k]==-1){tag=1;//說明進入一個新的位置phonelist[now].a[k]=++x; //給數組賦值now=x;//下一個位置}else{now=phonelist[now].a[k];if(phonelist[now].end)return 0; //單詞的結束標志}}phonelist[now].end=true; //標記結束的節點if(!tag) return 0;return 1; } int main() {//freopen("1.txt","r",stdin);int n,m;char s[12];scanf("%d",&n);while(n--){Init();scanf("%d",&m);for(int i=0;i<m;i++){scanf("%s",s);if(flag)flag=build(s);}if(flag)printf("YES\n");elseprintf("NO\n");}return 0; }

HDU 3746 Cyclic Nacklace

題意:

一個字符串,在串后面補全幾個字符,可以使他的全部字符最少循環2次以上,求最少補幾個字符?

題解:

kmp算法的next數組
next數組的含義為, T[0…i-1]中的最大公共真前綴/后綴, 對于0-indexed求出的next數組實際上為1-M

next[M]為T中的最大公共真前綴/后綴, 這樣M-next[M]應該就是循環節的長度len(仔細思考)
如果next[M]為0說明沒有循環節, M%len==0說明循環節完全重復包含

首先這里用到一個kmp算法的最長相等前后綴算法next[]
然后很重要的一點:補全后字符串循環體L為strlen(s)-next[n]
這里有三種可能性:
1,字符串里已經有兩次以上循環,而且都已補全這種就不用補全了,判斷方式: 相等前后綴肯定不為零,且總長n%L==0
2,字符串里已經有兩次以上循環,后續循環未補全這種要把單次循環的補全,由于已經有兩次以上的循環,那么前后綴肯定要比單次循環要長(懶得證明)那么 前后綴%單次循環 就是循環剩下來的: 比如 ababa 前后綴是aba 單次循環是 ab 剩下來的就是a那么我們要補全的就是 單詞循環-剩下來的: b ababa + b = ababab
3, 字符串里沒有兩次以上循環這種要補全兩次由于沒有兩次以上的循環,那么前后綴肯定要比單次循環要短(同上)那么我們就輸出 單詞循環-前后綴: l-next[n]這種可以和第二種合并

代碼:

#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int MAX=1e5+13; char w[MAX]; int cnt[MAX]; int F; void JZY(int len ) {F=-1;cnt[0]=-1;for(int i=0;i<len;){if(F==-1||w[i]==w[F]) cnt[++i]=++F;else F=cnt[F];} } int main() {int T;int m;scanf("%d",&T);while(T--){scanf("%s",w);int len=strlen(w);JZY(len);m=len-cnt[len];if((m!=len)&&(len%m==0)) printf("0\n");else printf("%d\n",m-cnt[len]%m);} }

HDU 2087 剪花布條

題意:

一個目標串,一個模板串,問目標串最多可以剪除幾個模板串?

題解:

可以用kmp來做,也可以用hash來做

代碼:

hash代碼:

#include<iostream> #include<vector> #include<algorithm> #include<string.h> #include<string> #include<cstdio> using namespace std; #define maxn 1001 string a; string b; const int B = 100000007; typedef unsigned long long ull; ull _hash(int al, int bl) {if (al < bl)return 0;ull t = 1, ah = 0, bh = 0, cnt = 0;for (int i = 0; i < bl; i++)t *= B;for (int i = 0; i < bl; i++)ah = ah*B + a[i];for (int i = 0; i < bl; i++)bh = bh*B + b[i];for (int i = 0; i + bl<=al; i++){//cout << a << "\n" << b << endl;//cout << ah << "\t" << bh << endl;if (ah == bh){cnt++;ah = ah - a[i + bl - 1] + '$';//這是關鍵一步,更改字母之后hash值發生變化,所以變化量為'$'-a[i+bl-1]a[i + bl-1] = '$';//更改已匹配的最后一個字母}if (i+bl<al)ah = ah*B - a[i] * t + a[i + bl];}return cnt; } int main() {while (cin>>a&&a!="#"){ cin >> b;int al = a.length();int bl = b.length();ull res = _hash(al, bl);cout << res << endl;} }

kmp代碼:

#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; const int maxx=1e6+10; int Next[maxx]; char s[maxx],p[maxx]; int len1,len2; void getnext() {int i=0,j=-1;Next[0]=-1;while(i<len1){if(j==-1||p[i]==p[j]){++i;++j;if(p[i]==p[j])Next[i]=Next[j];elseNext[i]=j;}elsej=Next[j];} } void getkmp() {int num=0,i=0,j=0;while(i<len2){if(j==-1|s[i]==p[j]){++i;++j;}elsej=Next[j];if(j==len1){++num;j=0;}}printf("%d\n",num); } int main() {while(scanf("%s",s),s[0]!='#'){scanf("%s",p);len1=strlen(p);len2=strlen(s);getnext();getkmp();}return 0; }

HDU 1251 統計難題

題意:

統計出以某個字符串為前綴的單詞數量

題解:

模板題,map也可以做

代碼:

#include<stdio.h> #include<string.h> #include<stdlib.h> #include<math.h> #include<algorithm> #include<iostream> #include<vector> #include<stack> #include<queue> #include<map> #include<set> #define inf 0x3f3f3f3f using namespace std; typedef long long LL; const int N=1e6+1; const int mod=1e9+7; const double pi=acos(-1); const double eps=1e-8; char s[12]; int trie[N][26],sum[N],tot,root; void sert() {root=0;for(int i=0;s[i]!='\0';i++){int id=s[i]-'a';if(!trie[root][id]) trie[root][id]=++tot;sum[trie[root][id]]++;root=trie[root][id];} } int finf() {root=0;int id;for(int i=0;s[i]!='\0';i++){id=s[i]-'a';if(!trie[root][id]) return 0;root=trie[root][id];}return sum[root]; } int main() {while(gets(s)){if(s[0]=='\0') break;sert();}while(gets(s)){printf("%d\n",finf());} }

HDU 2072 單詞數

題意:

統計不同單詞的數量

題解:

可以用map來做
不過練習字典樹

代碼:

#include<iostream> #include<sstream> using namespace std;struct node{int flag;struct node *next[26];node(){for(int i=0;i<26;i++){this->next[i]=NULL;}this->flag=0;} };node *root; int ans; void Insert(string str) {node *p=root;for(int i=0;i<str.size();i++){if(p->next[str[i]-'a']==NULL)p->next[str[i]-'a']=new node();p=p->next[str[i]-'a'];}p->flag++;if(p->flag==1)ans++; }int main() {string str,str1;while(getline(cin,str)){root=new node();ans=0;if(str=="#")break;istringstream ss(str);while(ss>>str1){Insert(str1);}cout<<ans<<endl;}return 0; } #include<iostream> #include<cstdio> #include<string> #include<algorithm> #include<set> #include<set> #include <sstream> using namespace std; int main() { string a; while(getline(cin,a)&& a != "#"){ istringstream stream(a);string w; set<string> map; while(stream >>w) map.insert(w); printf("%d\n",map.size()); }}

POJ 2513 Colored Sticks

題意:

給你一堆木棍。每根棍子的每個端點都用某種顏色著色。有沒有可能把棍子在一條直線上對齊,使接觸的端點的顏色是相同的顏色?

題解:

歐拉通路+并查集+字典樹
判斷歐拉通路是否存在的方法

有向圖:圖連通,有一個頂點出度大入度1,有一個頂點入度大出度1,其余都是出度=入度。

無向圖:圖連通,只有兩個頂點是奇數度,其余都是偶數度的。

代碼:

#include <cstdio> #include <cstring> int const MAX = 500005; int fa[MAX], d[MAX], cnt;struct Trie {int sz, t[MAX][15];int jud[MAX];Trie(){sz = 1;memset(t[0], -1, sizeof(t));jud[0] = 0;}void clear(){sz = 1;memset(t[0], -1, sizeof(t));jud[0] = 0;}int idx(char c){return c - 'a';}void insert(char* s, int v){int u = 0, len = strlen(s);for(int i = 0; i < len; i++){int c = idx(s[i]);if(t[u][c] == -1){memset(t[sz], -1, sizeof(t[sz]));jud[sz] = 0;t[u][c] = sz++;}u = t[u][c];}jud[u] = v;}int search(char* s){int u = 0, len = strlen(s);for(int i = 0; i < len; i++){int c = idx(s[i]);if(t[u][c] == -1) return -1;u = t[u][c];}if(jud[u]) return jud[u];return -1;} }t;void Init() {for(int i = 0; i < MAX; i++)fa[i] = i; }int Find(int x) {return x == fa[x] ? x : fa[x] = Find(fa[x]); }void Union(int a, int b) {int r1 = Find(a);int r2 = Find(b);if(r1 != r2)fa[r1] = r2; }bool eluer() {int sum = 0, t = -1;for(int i = 1; i < cnt; i++)if(d[i] % 2) sum++;if(sum != 0 && sum != 2)return false;for(int i = 1; i < cnt; i++){if(t == -1)t = Find(i);else if(Find(i) != Find(t)) return false;}return true; }int main() {char s1[20],s2[20];cnt = 1;Init();t.clear();while(scanf("%s %s", s1, s2) != EOF){if(t.search(s1) == -1)t.insert(s1, cnt++);int u = t.search(s1);if(t.search(s2) == -1)t.insert(s2, cnt++);int v = t.search(s2);Union(u, v);d[u]++;d[v]++;}if(eluer())printf("Possible\n");elseprintf("Impossible\n"); }

總結

以上是生活随笔為你收集整理的KMP Trie 例题讲解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 91九色在线视频 | 毛片看看 | 一级aaaa毛片 | 天天操天天操天天干 | 视频二区在线 | 国产欧美日韩专区 | 国产婷婷色综合av蜜臀av | 天天色天天操天天射 | 狠狠爱亚洲 | 好吊色视频一区二区三区 | 天堂久久网 | 麻豆911| 四虎福利 | 久久精品色欲国产AV一区二区 | 潘金莲三级80分钟 | 中文字幕亚洲欧美日韩在线不卡 | 日韩毛片在线 | 射综合网| 老鸭窝成人 | 国产熟妇搡bbbb搡bbbb搡 | 91视频在线观看网站 | av片网| 日本毛片在线 | 日韩精品国产一区 | 国产91av视频 | 色图综合 | 午夜一区二区三区免费观看 | 午夜家庭影院 | 欧美一区二区久久 | www.日本在线观看 | 久久五月天av | 国产成人精品亚洲日本在线观看 | 91这里只有精品 | 日韩a√| 精品一二三区 | 日韩黄色一区二区 | av大西瓜| 国产欧美视频一区 | 亚洲免费在线观看av | 午夜精品国产 | 亚洲一级av毛片 | 你懂的在线播放 | 女人叫床高潮娇喘声录音mp3 | 91好色先生tv| 九九热视频在线观看 | 亚洲日日日 | 污网址在线观看 | 人妻少妇一区二区 | 国产精品第1页 | 亚洲第一黄色网址 | 亚洲视频在线观看一区二区三区 | 色亚洲色图 | 中文字幕免费观看 | 久草福利 | 亚洲天堂麻豆 | 狠狠干91| 2021av| 韩国中文三级hd字幕 | 爆操少妇 | 久久久天堂 | 91精品亚洲 | 肉嫁高柳在线 | 国产精品久久久影院 | 日韩欧美高清在线观看 | 日韩成人一区二区视频 | 巨乳女教师的诱惑 | 日日爱886 | 亚洲麻豆视频 | 动漫美女露胸网站 | 91操操操| 日本亚洲最大的色成网站www | 亚洲精品免费在线观看视频 | www夜夜 | 亚洲性xxx| 草草影院最新地址 | 国产va在线观看 | 性开放淫合集 | 精品欧美激情精品一区 | 操模特 | 国产在线视频导航 | 超碰免费91 | 亚洲av无码片一区二区三区 | 在线免费黄 | 亚洲永久精品视频 | 欧美成人女星 | 国产午夜精品一区二区三区四区 | 麻豆成人入口 | 色臀av| 91精品国产综合久久久蜜臀九色 | 亚洲AV无码久久精品国产一区 | 日韩爆操 | 稀缺小u女呦精品呦 | 99久久国| 一出一进一爽一粗一大视频 | 成人77777| 久久九九久精品国产免费直播 | 人人干在线 | 女人脱下裤子让男人捅 | 欧美极品少妇xxxxⅹ猛交 |