【ybtoj】【字典樹】單詞拼接
阿新 • • 發佈:2021-09-06
題意
E. 1.單詞拼接
題目描述
給定由一些單片語成的詞典。
一個單詞是特殊的,當且僅當它能由詞典裡的兩個單詞拼接而成。
求詞典裡特殊的單詞數。
輸入格式
一行一個字串,表示詞典裡的一個單詞。每個字串由小寫字母組成,每個字串按字典序排列,每個字串只會出現一次。
輸出格式
一行一個字串,按字典序輸出所有特殊的單詞。
樣例
樣例輸入
a ahat hat hatword hziee word
樣例輸出
ahat hatword
題解
兩種方法
方法一:把每個串先都插入字典樹裡,之後暴力列舉每一個串的前半部分和後半部分,如果都能前後兩部分都能在字典樹中找到,那說明這個字串是特殊的
方法二:把每個串正反(正反串記為S1,S2)分別插入兩個字典樹(記為A,B),同時記錄正串和反串能被完整字元覆蓋的字首,如果∃ i,使得 S1[ i ]==S2[ len-i ],就說明原串是特殊的
Tips:
- 我第一次知道還可以在while(scanf)外面輸出
while(scanf("%s",s+1)!=EOF)
{
...
}
for(int i=1;i<=n;i++) printf..
- 這題資料範圍給錯了,要開 5e4,RE了好久才發現
程式碼
單詞拆分
#include<bits/stdc++.h> using namespace std; #define ll long long const int INF = 0x3f3f3f3f,N = 50010; int n,tot=1; char s[N][33]; int trie[N<<5][30],ans,ed[N<<5]; void insert(int id) { int p=1,len=strlen(s[id]+1); for(int i=1;i<=len;i++) { int ch=s[id][i]-'a'; if(!trie[p][ch]) trie[p][ch]=++tot; p=trie[p][ch]; } ed[p]++; } int find(int id,int l,int r) { int p=1; for(int i=l;i<=r;i++) { int ch=s[id][i]-'a'; if(!trie[p][ch]) return 0; p=trie[p][ch]; } return ed[p]; } int main() { int now=1; while(scanf("%s",s[now]+1)!=EOF) { insert(now); now++; } for(int i=1;i<=now-1;i++) { int len=strlen(s[i]+1); //printf("len=%d\n",len); for(int k=1;k<len;k++) if(find(i,1,k)&&find(i,k+1,len)) { printf("%s\n",s[i]+1); break; } } return 0; }