Description
某人有一套玩具,并想法给玩具命名。首先他选择WING四个字母中的任意一个字母作为玩具的基本名字。然后
他会根据自己的喜好,将名字中任意一个字母用“WING”中任意两个字母代替,使得自己的名字能够扩充得很长。
现在,他想请你猜猜某一个很长的名字,最初可能是由哪几个字母变形过来的。
Input
第一行四个整数W、I、N、G。表示每一个字母能由几种两个字母所替代。接下来W行,每行两个字母,表示W可
以用这两个字母替代。接下来I行,每行两个字母,表示I可以用这两个字母替代。接下来N行,每行两个字母,表示N
可以用这两个字母替代。接下来G行,每行两个字母,表示G可以用这两个字母替代。最后一行一个长度不超过Len的
字符串。表示这个玩具的名字。
Output
一行字符串,该名字可能由哪些字母变形而得到。(按照WING的顺序输出)如果给的名字不能由任何一个字母
变形而得到则输出“The name is wrong!”
思路:区间动态规划
f{l,r,k}表示字符串s从l到r是否能够转化成k.
转移方程为f{l,r,k}=f{l,j,a}&&f{j+1,r,b} (l<=j<r) k可以转化成ab.
我们采用记忆化搜索将结果存储起来。
遍历t[k](k可以转化的两个字母)
对len进行区间化分进行讨论(l<=j<r).分别讨论dp[l][j][a]&&dp[j+1][r][b].
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class __1055 {
static int[] t=new int[4];
static List<String[]> list=new ArrayList<String[]>();
static int[][][] f=new int[205][205][4];
static String s;
static char[] p={'W','I','N','G'};
static int[] q=new int[255];
public static boolean dp(int l,int r,int k){
if(l==r){
return s.charAt(l)==p[k];
}
int res=f[l][r][k];
if(res!=-1){
return res==1;
}
for(int i=0;i<t[k];++i){
for(int j=l;j<=r-1;++j){
if(dp(l,j,q[list.get(k)[i].charAt(0)])&&dp(j+1,r,q[list.get(k)[i].charAt(1)])){
f[l][r][k]=1;
return true;
}
}
}
f[l][r][k]=0;
return false;
}
public static void main(String[] args){
Scanner cin=new Scanner(System.in);
q['W']=0; //预处理方便获取当前字符
q['I']=1;
q['N']=2;
q['G']=3;
for (int i = 0; i < f.length; i++) {
for (int j = 0; j < f[i].length; j++) {
for (int k = 0; k < f[i][j].length; k++) {
f[i][j][k]=-1;
}
}
} //初始化 -1表示没处理过 0表示可以转化 1表示可以转化
for(int i=0;i<4;++i){
t[i]=cin.nextInt();
}
for(int i=0;i<4;++i){
String[] tmp=new String[t[i]];
for(int j=0;j<t[i];++j){
tmp[j]=cin.next();
}
list.add(tmp);
}
s=cin.next();
int len=s.length()-1;
boolean flag=false;
for(int i=0;i<4;++i){
if(dp(0,len,i)){
flag=true;
System.out.print(p[i]);
}
}
if(!flag){
System.out.println("The name is wrong!");
}
}
}