HDU1247 Hat’s Words(前缀树 + 字符串处理)

题目贴上:
在这里插入图片描述
题目大意:首先给你一系列字符串,需要你找出是否存在某个字符串由给定的另外两个单词顺序串接而成,存在输出这个字符串,输入直至文件末

题目思路:首先将所有单词存入一棵前缀树当中,然后遍历每个字符串,对字符串进行切割(最小长度为1,最大不能等于这个原字符串长度),将切割出来的两个字符串在前缀树中搜索,如果都存在,输出这个原字符串。

题目的坑点:我设想了一种情况,比如给定有a,aa,而aa可以分割成两个a,我认为aa不符合情况,因为题目说是“另外两个字符串”,我潜意识认为这另外两个字符串应该不相同,然后,哦豁,疯狂WA,我吐了啊~~
题目的坑永远是无法琢磨的,更何况这个题目连单词长度限制也没说,我直接改用string,这样子你那我没办法了吧→_→

#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <string>
#include <iomanip>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <stack>
#include <map>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define endl '\n'
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long int ll;
typedef __int64 bi;
typedef pair<ll,ll> PII;
const int maxn = 1e6+200;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1.0);
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0',  ch = getchar();return x*f; }
int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };

struct trie{
	int tree[1000008][26],cnt;
	bool color[1000008];

	// 插入一个新单词
	void insert(string s,int l){
		int p = 0;
		for(int i=0;i<l;++i){
			int c = s[i] - 'a';
			if(!tree[p][c])
				tree[p][c] = ++cnt;
			p = tree[p][c];
		}
		color[p] = true;
	}

	// 查找前缀访问的次数,也就是某个前缀在单词中出现的次数
	bool search(string s,int l){
		int p = 0;
		for(int i=0;i<l;++i){
			int c = s[i] - 'a';
			if(!tree[p][c]) return 0;
			p = tree[p][c];
		}
		return color[p];
	}

	void clear(){
		mem(tree,0);
		mem(color,0);
		cnt = 0;
	}
};
struct trie tr;

signed main(void)
{
	string s;
	vector<string> v;
	while(cin>>s && !cin.eof()){
		v.pb(s);
		tr.insert(s,s.size());
	}
	int size = 0;
	string fi="",se="";
	for(auto i : v){
		size = i.length();
		fi = "";
		se = "";
		//cout << i <<"---------------------"<<endl;
		for(int j=0;j<size-1;++j){
			fi = i.substr(0,j+1);
			se = i.substr(j+1,size-(j+1));
			//cout<<fi <<"     "<<se<<endl;
			// 千万不要在下面if里面加 fi!=se,不过被坑死了!!!
			if(tr.search(fi,fi.size()) && tr.search(se,se.size())){
				cout << i << endl;
				break;
			}
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凌晨小街

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值