题意
对于两个字符串s1
和s2
。
先把s3
和s4
都设为s1
,然后循环这样的操作:
- 对于第
i
次操作,从s3
里把s2
字符串的第i
个字符全部删掉。 - 然后把
s3
加在s4
的最后面。 - 知道
s2
里的字符全部都扫一遍结束。
举个例子:
s1
是abacaba
,s2
是bac
,那么步骤是这样的:
- 一开始,
s4
就是s1
,也就是abacaba
- 第1次操作:把所有
b
删掉(s2
第1个字符,结果即aacaa
)加后面,s4
变成abacabaaacaa
- 第2次操作,把所有
a
删掉(s2
第1个字符,结果即c
)加后面,s4
变成abacabaaacaac
- 第3次操作,把所有
c
删掉,现在删干净了,把空串加到s4
后面。s4
最后就是abacabaaacaac
了!
你以为这是个模拟,给你一个s1
和一个s2
让你求s4
?NAIVE!
这个题给你t个s4
,让你反求每个s4
对应的s1
和s2
是什么。
如果推不出来,输出-1
。
思路
关键点1:可以发现,如果我把s4
从后到前扫一遍,看看每种字符第一次出现的次序是怎样的,把每种字符按次序写出来,这个写出来的字符串正好是s2
倒过来
比如:abacabaaacaac
,从后往前看,先看到c
,再看到a
,最后看到b
,写出来就是cab
,正好是bac
反过来写的样子。
可以这样想想看,最后一次的操作一定会把这个字符串删成空串。倒数第二次呢?肯定要么是一个单独的字符,要么是若干个这个字符。
这样想是不是就可以想明白这个关键点为啥对了。倒过来看,我可以反推删除顺序。
关键点2:s1
绝对是s4
的前缀
这根据定义就看出来了,我一上来在s4
前面放的就是s1
,怎么可能不是前缀。
虽然很显然,但是很关键。
关键点3:如果能推出来的话,知道s2
和s4
,可以知道s1
有多长
首先想一个问题,如果知道s1
有多长,结合上面的关键点2,是不是可以直接获得s1
是什么。
那如果我们知道s1
是什么了,我们根据最上面的题目意思,拿s1
和s2
跑一遍模拟,看看是不是跟题目给我们的s4
相同,我们就可以验证-1
这种情况了。
对于关键点3怎么证明,看关键点4。
关键点4:s4
里某一个字符出现的次数,与这个字符在s1
里的出现次数成倍数关系,倍数就是这个字符在s2
里的位置(第一个位置是1)
有了这个关键点4,s1
真的就能求了,举个例子:
假设s4
是abacabaaacaac
,我们推出s2
是bac
了。
那么在s4
里b
出现了2次,a
出现了8次,c
出现了3次。
那么根据这个关键点,在s1
里,b
应该出现2/1=2次,a
出现8/2=4次,c
出现3/3=1次,s1
长度就该是2+4+1=7,也就是s4
前7个字符,得到如果存在的话,s1
就是abacaba
了。
这个关键点是为啥呢?很显然,出现的次数就是被删掉的次序,也恰好是s1
里所有这种字符在s4
里重复的遍数,这样就能想明白这个倍数关系是为啥了。
那么这样看来,s1
和s2
都可以反推,我们模拟验证一下能不能得出题目给的s4
,能就直接输出s1
s2
,不能输出-1
就OK了。
代码
import java.util.*;
public class Main {
private static Scanner scanner = new Scanner(System.in);
public static void main(String[] args) {
int t = scanner.nextInt();
while (t-- > 0) {
solve();
}
}
public static void solve() {
String s = scanner.next();
Set<Character> set = new HashSet<>();
StringBuilder s2 = new StringBuilder();
Map<Character, Integer> mp = new HashMap<>();
for (int i = s.length() - 1; i >= 0; i--) {
char c = s.charAt(i);
mp.put(c, mp.getOrDefault(c, 0) + 1);
if (set.contains(c)) continue;
set.add(c);
s2.append(c);
}
s2 = s2.reverse();
int len = 0;
for (int i = 1; i <= set.size(); i++) {
char c = s2.charAt(i - 1);
int p = mp.get(c);
len += p / i;
}
String s1 = s.substring(0, len);
StringBuilder sb = new StringBuilder(s1);
char[] cs = s2.toString().toCharArray();
String ts = s1;
for (char c : cs) {
ts = ts.replace("" + c, "");
sb = sb.append(ts);
}
if (sb.toString().equals(s)) {
System.out.println(s1 + " " + s2);
} else {
System.out.println(-1);
}
}
}