涉及算法:dp
题目大意:现有一个长度为m的字符串s和n个单词,现在需要删除字符串中的某些字符,使得剩下的部分可以用n个单词的中的某些来表示,求最少需要删除多少个字符。
题目分析:设dp[i]表示从s的第0个字符开始长度为i的字符串(末位位i-1,后面的字符不考虑)需要删除的字符数,则dp[i]是取决于dp[1]~dp[i-1]的,如果s[i]加上其前面的一些字符(可以不连续)能和某个word匹配,则dp[i]取决于dp[k]和匹配需要该word需要从s中删除的字符数,k为s与该word匹配的最后一个字符的索引,若s[i]加上其前面的一些字符(可以不连续)不能某个word匹配,则s[i]显然是要删除,那么dp[i]=dp[i-1]+1;根据这些分析,可以得到如下的状态转移方程:
其中k为和该word匹配的最后一个字符的索引。
代码如下:
题目大意:现有一个长度为m的字符串s和n个单词,现在需要删除字符串中的某些字符,使得剩下的部分可以用n个单词的中的某些来表示,求最少需要删除多少个字符。
题目分析:设dp[i]表示从s的第0个字符开始长度为i的字符串(末位位i-1,后面的字符不考虑)需要删除的字符数,则dp[i]是取决于dp[1]~dp[i-1]的,如果s[i]加上其前面的一些字符(可以不连续)能和某个word匹配,则dp[i]取决于dp[k]和匹配需要该word需要从s中删除的字符数,k为s与该word匹配的最后一个字符的索引,若s[i]加上其前面的一些字符(可以不连续)不能某个word匹配,则s[i]显然是要删除,那么dp[i]=dp[i-1]+1;根据这些分析,可以得到如下的状态转移方程:
其中k为和该word匹配的最后一个字符的索引。
代码如下:
package com.solo.dp;
import java.util.Scanner;
public class Main_3267 {
static String[] word;//用来匹配字符串的单词
static char[] str;//字符串
static int[] len;//len[i]:第i个单词的长度
static int[] dp;//dp[i]:
static int m;//字符串长度
static int n;//单词个数
public static void main(String[] args)
{
Scanner in=new Scanner(System.in);
n=in.nextInt();
m=in.nextInt();
dp=new int[m+1];
word=new String[n];
len=new int[n];
String s=in.next();
str=s.toCharArray();
for(int i=0;i<n;i++)
{
word[i]=in.next();
len[i]=word[i].length();
}
dp();
System.out.println(dp[0]);
}
//从后往前走
static void dp(){
//dp[i]:表示从第i位到末位需要删除的字符个数
dp[m]=0;
for(int i=m-1;i>=0;i--)
{
dp[i]=dp[i+1]+1;
for(int j=0;j<n;j++)
{
if((m-i)>=len[j] && str[i]==word[j].charAt(0))//若str[i]和word的第一个字符不一样,则str[i]肯定是要删除的
{
int wid=1;
for(int k=i+1;k<m;k++)
{
if(str[k]==word[j].charAt(wid))
{
wid++;
if(wid==len[j])
{//匹配成功
dp[i]=Math.min(dp[i],dp[k+1]+k-i+1-len[j]);
break;
}
}
}
}
}
}
}
//从前往后走
static void dp2(){
//dp[i]:表示从第0位开始长度为i的字符串(末位为第i-1个字符)
dp[0]=0;
for(int i=1;i<=m;i++)
{
dp[i]=dp[i-1]+1;
for(int j=0;j<n;j++)
{
if(str[i-1]==word[j].charAt(len[j]-1) && i>=len[j])
{
int wid=len[j]-2;
for(int k=i-2;k>=0;k--)
{
if(str[k]==word[j].charAt(wid))
{
wid--;
if(wid==-1)
{
dp[i]=Math.min(dp[i], dp[k]+i-k-len[j]);
break;
}
}
}
}
}
}
}
}