LA 3942 Remember the Word

本文介绍了一种结合字典树与动态规划(DP)的算法,用于解决字符串分解问题。具体而言,该算法利用字典树进行高效匹配,并通过动态规划计算字符串分解的方法数量。文中提供了一个完整的代码实现案例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        题意:给出一个由s个不同的单词组成的字典和一个长字符串str。把这个字符串分解成若干个单词的连接(可重复使用),求有多少种不同的分法。

        思路:字典树+dp。用字典树去匹配单词,并dp计数。dp(x)表示从str[x]到末尾的分解方法数。如果str[i]~str[j]正好与某个单词相匹配,那么dp(i)就应该加上dp(j)。字典树的建树主要参考了大白书。


#include <iostream>           
#include <stdio.h>           
#include <cmath>           
#include <algorithm>           
#include <iomanip>           
#include <cstdlib>           
#include <string>           
#include <memory.h>           
#include <vector>           
#include <queue>           
#include <stack>           
#include <map>         
#include <set>         
#include <ctype.h>           
#define INF 1<<30       
#define ll long long       
#define max3(a,b,c) max(a,max(b,c))       
#define MAXA 100000  
  
using namespace std;  

char text[300010];
char word[4010][110];
int dp[600010];

struct Trie{
	int ch[300010][26];
	int val[300010];
	int sz;
	
	void init(){
		sz=1;
		memset(ch[0],0,sizeof(ch[0]));
	}
	
	void insert(char* str,int v){
		int u=0;
		int len=strlen(str);
		for(int i=0;i<len;i++){
			if(!ch[u][str[i]-'a']){
				memset(ch[sz],0,sizeof(ch[sz]));
				val[sz]=0;
				ch[u][str[i]-'a']=sz++;
			}
			u=ch[u][str[i]-'a'];
		}
		val[u]=v;
	}
	
	bool sear(char* str,int s,int len){
		int u=0;
		for(int i=0;i<len;i++){
			if(!ch[u][str[i]-'a'])return 0;
			u=ch[u][str[i]-'a'];
			if(val[u]){
				dp[s]+=dp[s+i+1];
				dp[s]%=20071027;
			}
		}
		if(!val[u])return 0;
		return 1;
	}
};

Trie root;

int main(){
	int cas=0;
	while(~scanf("%s",text)){
		root.init();
		cas++;
		memset(dp,0,sizeof(dp));
		
		int n;
		cin>>n;
		
		for(int i=1;i<=n;i++){
			scanf("%s",word[i]);
			root.insert(word[i],1);
		}
		
		int end=strlen(text);
		dp[end]=1;
		for(int i=end-1;i>=0;i--){
			root.sear(text+i,i,end-i);
		}
		printf("Case %d: %d\n",cas,dp[0]);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值