ZOJ(3455)

Shizuka's Letter


Time Limit: 2 Seconds      Memory Limit: 65536 KB

Nobita receives a letter from Shizuka. For the sake of security, the letter's content T is produced as follows, first the message is written, then the substitution cipher and transposition cipher is applied to the message. Finally, the encrypted message is inserted into another text.

Substitution cipher changes all occurrences of each letter to some other letter. Substitutes for all letters must be different. For example, after substitution cipher, the message "BBA" can become "AAC".

Transposition cipher applies some permutation to the letters of the message. For example, after applying the permutation (1, 3, 2), the second letter moves to the third place, the third letter moves to the second place, so the message "AAC" turns to "ACA".

For example, suppose the original message is "BBA", after substitution, it becomes "AAC", then after transposition, it becomes "ACA". Finally the encrypted message "ACA" is inserted into another text "CBC", after letter 'B', so the content of the letter is "CBACAC".

Nobita don't know what the original message is, but he guesses the message should be P. Now given the letter's content T and Nobita's guess P, you should determine if Nobita's guess is possible to be right.

Input

There are multiple cases.

For each case, the first line is letter's content T, the second line is Nobita's guess PP and T are strings consist of characters whose ASCII code is between 33 ('!') and 126 ('~'). The length of P and T is no more than 500000. P is guaranteed to be shorter than T.

Output

For each case, if Nobita's guess is possible to be right, output "Yes", otherwise output "No". If the answer is "Yes", it should be followed by another line of integers which denote all the positions (0-based) of the message in the content.

Sample Input

CBACAC
BBA
ABCDE
BBA

Sample Output

Yes
2 3
No
转:http://blog.watashi.ws/1760/zojmonthly1012/
题意:有一种加密方法,对于字符串P,首先将字符串中的字符进行替换,然后可以对位置进行交换,最后将它插入另一个字符串中间获得加密串T。然后对于一对T与P,求T是否可以为P的一个加密结果,若是则求所有的加密位置。
思路:首先只考虑替换和交换这两步,那么会知道,这样变化后会满足出现i次的字母的个数l[i]是不变的,反之,如果满足这个条件,则一定可以通过替换加交换得到。而从位置j到位置j+1,多了一个字符T[j+n],少了T[j],所以最多有两个l[i]发生了变化。如果我们用一个变量k,记录有多少l[i]与P的一致,那么k==SIGMA的时候,就是一个合法的位置。每一步,这些变量都可以在O(1)的时间内得到维护,所以总的复杂度是O(n)的。
难点:维护k。
 1 #include<cstdio>
 2 #include<vector>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 #define  maxn 500500
 7 #define ASCII 256
 8 int c[ASCII];
 9 int l[maxn];
10 char T[maxn];
11 char P[maxn];
12 int main()
13 {
14     int n,m,k;
15     vector<int>ans;
16     while(~scanf("%s%s",T,P))
17     {
18         n=strlen(T);
19         m=strlen(P);
20         fill(c,c+ASCII,0);
21         for(int i=0;i<m;i++)//字符作下标对应的是是ASCII码。
22             c[P[i]]++;
23         fill(l+1,l+1+m,0);
24         for(int i=0;i<ASCII;i++)
25             l[c[i]]--;
26         k=count(l+1,l+1+m,0);
27 
28         ans.clear();
29         fill(c,c+ASCII,0);
30         for(int i=0;i<n;i++)
31         {
32             if(i>=m)
33             {
34                 int &temp1=c[T[i-m]];//不能掉了引用符号
35                 if(l[temp1]==0)
36                     k--;
37                 if(l[temp1]==1)
38                     k++;
39                 l[temp1]--;
40                 temp1--;
41                 if(temp1!=0)
42                 {
43                     if(l[temp1]==-1)
44                         k++;
45                      if(l[temp1]==0)
46                         k--;
47                     l[temp1]++;
48                 }
49             }
50             int &temp2=c[T[i]];
51             if(temp2!=0)
52             {
53                 if(l[temp2]==0)
54                     k--;
55                 if(l[temp2]==1)
56                     k++;
57                 l[temp2]--;
58             }
59             temp2++;
60             if(l[temp2]==-1)
61             k++;
62             if(l[temp2]==0)
63             k--;
64             l[temp2]++;
65             if(k==m)
66             {
67                 ans.push_back(i-m+1);
68             }
69         }
70         if(ans.empty())
71             puts("No");
72         else
73         {
74             puts("Yes");
75             for(int i=0;i<ans.size();i++)
76                 printf(i==ans.size()-1?"%d
":"%d ",ans[i]);
77         }
78     }
79     return 0;
80 }
原文地址:https://www.cnblogs.com/ZP-Better/p/4686903.html