【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
",len); 
			for(int k=1;k<len;k++)	
				if(find(i,1,k)&&find(i,k+1,len)) 
				{
					printf("%s
",s[i]+1);
					break;
				}
		}
	return 0;
}
原文地址:https://www.cnblogs.com/conprour/p/15231333.html