100723H Obfuscation

传送门

题目大意

给你一个包含n 个单词的字典,给你一篇文章,文章包括若干词典里的单词,把句子里的空格都去掉,单词的首位字母都不变,中间的字符集为乱序,问能否恢复这篇文章,使得单词都是词典里的单词,如果有唯一解,输出唯一解。

分析

可以将将一段字符串哈希来确定这段字符串的字母组成,在记录每一段的首字母和尾字母,这样便可以将整段字符表示出来了,在进行完预处理之后我们进行dp,用dpi表示i+1到m这一段的字符可以由先有字母表组成几个。最后如果dp0有0个则代表无法组成,大于1则有歧义,等于一则根据之前记录的nxt数组和每一段字符对应的编号将答案输出。详见代码。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
#define sp cout<<"---------------------------------------------------"<<endl
#define uli unsigned long long
#define li long long
char bs[10002],s[10002][102];
uli wsh[30];
int len[10002],dp[1002],nxt[1002];
map<uli,int>mp[28][28];
multiset<uli>HASH[28][28];
int main(){
      srand(time(0)+1010101);
      int n,m,i,j,t;
      for(i=0;i<28;i++)
        wsh[i]=(uli)rand()*rand()*rand()*rand()*rand()*rand()*rand()*rand();
      scanf("%d",&t);
      while(t--){
          for(i=0;i<26;i++)
            for(j=0;j<26;j++){
                HASH[i][j].clear();
                mp[i][j].clear();
            }
          scanf("%s",bs);
          scanf("%d",&n);
          m=strlen(bs);
        for(i=1;i<=n;i++){
          scanf("%s",s[i]);
          len[i]=strlen(s[i]);
          uli hsh=0;
          for(j=0;j<len[i];j++)
            hsh+=wsh[s[i][j]-'a'];
          HASH[s[i][0]-'a'][s[i][len[i]-1]-'a'].insert(hsh);
          mp[s[i][0]-'a'][s[i][len[i]-1]-'a'][hsh]=i;
        }
        memset(dp,0,sizeof(dp));
        memset(nxt,0,sizeof(nxt));
        dp[m]=1;
        for(i=m-1;i>=0;i--){
          uli hsh=0;
          for(j=i;j<m;j++){
              hsh+=wsh[bs[j]-'a'];
            int x=HASH[bs[i]-'a'][bs[j]-'a'].count(hsh);
            if(x>0&&dp[j+1]){
                dp[i]+=x*dp[j+1];
                nxt[i]=j+1;
            }
          }
          dp[i]=min(dp[i],2);
        }
        if(dp[0]==0)puts("impossible");
          else if(dp[0]>1)puts("ambiguous");
          else {
              for(i=0;i<m;i=nxt[i]){
                uli hsh=0;
                for(j=i;j<nxt[i];j++)
                  hsh+=wsh[bs[j]-'a'];
                printf("%s ",s[mp[bs[i]-'a'][bs[nxt[i]-1]-'a'][hsh]]);
            }
            puts("");
          }
      }
      return 0;
}
原文地址:https://www.cnblogs.com/yzxverygood/p/9346300.html