题意
一堆字符串由许多个单词组成,但是除了单词的开始和结尾都做了一定程度的乱序。要求破解这个被打乱的句子。
题解
HASH+DP(暴力)。首先对单词进行处理,将单词去掉头和尾记录到头和尾组成的哈希表中。对于长度为1的单词特殊记录。然后进行暴力搜索(DP)。暴力搜索从0开始,0可能是从0开始到0-100区间内组成的任意一个的单词的字符(因为单词长度最大为100,这个需要特别注意,会不会TLE就看这个了)。于是我们便可以去针对每一个可能的字符串去哈希表里搜索,如果搜索到了那么就可以进行状态转移。
对于一个单词,可以状态转移到现有长度+单词长度的位置。因为涉及到是否存在模糊字符串的判断,因此在转移的时候需要分情况讨论。对于模糊的单词,状态转移之后的值应该为2。而对于非模糊的单词,则应该视情况而定,并且需要记录对应单词,因为非模糊单词是有可能组成最后结果的。
最后暴力搜索完以后,判断一下是否能形成合法答案,输出一下就可以了。
代码
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
public class Main{
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
int ks=scanner.nextInt();
Map<String, String> first[][]=new HashMap[30][30];
Set<String> second[][]=new HashSet[30][30];
for (int i = 0; i < 30; i++) {
for (int j = 0; j < 30; j++) {
first[i][j]=new HashMap<String,String>();
second[i][j]=new HashSet<String>();
}
}
while(ks!=0){
boolean single[]=new boolean[30];
String string=scanner.next();
int len=string.length();
ks--;
int n=scanner.nextInt();
for (int i = 0; i < 30; i++) {
for (int j = 0; j < 30; j++) {
first[i][j].clear();
second[i][j].clear();
}
}
for (int i = 0; i < n; i++) {
String word=scanner.next();
if(word.length()==1){
single[word.charAt(0)-'a']=true;
}else{
int a=word.charAt(0)-'a';
int b=word.charAt(word.length()-1)-'a';
char arr[]=word.substring(1, word.length()-1).toCharArray();
Arrays.sort(arr);
String sortStr=String.valueOf(arr);
if(first[a][b].containsKey(sortStr)){
second[a][b].add(sortStr);
}else {
first[a][b].put(sortStr, word);
}
}
}
int way[]=new int[1100];
String pre[]=new String[1100];
way[0]=1;
for (int i = 0; i < len; i++) {
if(way[i]>0){
if(single[string.charAt(i)-'a']){
way[i+1]=Math.min(way[i+1]+way[i],2);
pre[i+1]=String.valueOf(string.charAt(i));
}
for (int j = i+2; j <= len&&(j-i)<=100; j++) {
int a=string.charAt(i)-'a';
int b=string.charAt(j-1)-'a';
String word=string.substring(i+1, j-1);
char arr[]=word.toCharArray();
Arrays.sort(arr);
String sortStr=String.valueOf(arr);
if(second[a][b].contains(sortStr)){
way[j]=Math.min(way[j]+2*way[i],2);
}else if(first[a][b].containsKey(sortStr)){
way[j]=Math.min(way[j]+way[i],2);
pre[j]=first[a][b].get(sortStr);
}
}
}
}
if(way[len]==2){
System.out.println("ambiguous");
}else if(way[len]==0){
System.out.println("impossible");
}else {
List<String> ans=new ArrayList<String>();
for(int i=len;i>0;i-=pre[i].length()){
ans.add(pre[i]);
}
Collections.reverse(ans);
for (int i = 0; i < ans.size(); i++) {
if(i!=0)
System.out.print(" ");
System.out.print(ans.get(i));
}
System.out.println();
}
}
}
}