1. 程式人生 > 其它 >【ybtoj】【字典樹】單詞拼接

【ybtoj】【字典樹】單詞拼接

題意

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;
}