1、2018 京東校招筆試題 兩個子串
題目描述
給定一個字符串s, 請計算輸出含有連續兩個s作爲子串的最短字符串。 注意兩個s可能有重疊部分。例如,"ababa"含有兩個"aba".
輸入描述:
輸入包括一個字符串s,字符串長度length(1 ≤ length ≤ 50),s中每個字符都是小寫字母.
輸出描述:
輸出一個字符串,即含有連續兩個s作爲子串的最短字符串。
示例1
輸入
abracadabra
輸出
abracadabracadabra
思路如下圖:
實現代碼:
#include<iostream>
#include<string>
using namespace std;
int* getNextArray(string str2) {
if (str2.length() == 1) {
int* next = new int[1];
next[0] = -1;
return next;
}
int* next = new int[str2.length()];
next[0] = -1;
next[1] = 0;
int i = 2;
int cn = 0;
while (i < str2.length()+1) {//多求一位
if (str2[i - 1] == str2[cn]) {
next[i++] = ++cn;
}
else if (cn > 0) {
cn = next[cn];
}
else {
next[i++] = 0;
}
}
return next;
}
int main() {
string s1;
while (cin >> s1) {
int* p = getNextArray(s1);
string res = s1 + s1.substr(p[s1.length()]);
cout << res;
}
return 0;
}
2、判斷二叉樹B是否爲二叉樹A的子樹
思路:序列化二叉樹+KMP算法
即將兩顆二叉樹序列化然後判斷B(tree2)序列化的結果是否爲A(tree1)序列化的子串即可
完整代碼:
#include<iostream>
#include<stack>
#include<string>
using namespace std;
struct TreeNode {
int val;
struct TreeNode* left;
struct TreeNode* right;
TreeNode(int data):val(data), left(NULL),right(NULL){
}
};
//先序序列遍歷
void preOrder(TreeNode* root) {
if (root != NULL) {
stack<TreeNode*> s;
s.push(root);
while (!s.empty()) {
TreeNode* p = s.top();
s.pop();
cout << p->val;
if (p->right != NULL)
s.push(p->right);
if (p->left != NULL)
s.push(p->left);
}
cout << endl;
}
}
//先序創建二叉樹
TreeNode* preCreate() {
int data;
TreeNode *p;
cin >> data;
if (data == -1) {
p = NULL;
}
else {
p = new TreeNode(data);
p->left = preCreate();
p->right = preCreate();
}
return p;
}
//先序序列化
string preSerial(TreeNode* root) {
if (root == NULL) {
return "#_";
}
string res = to_string(root->val) + '_';
res += preSerial(root->left);
res += preSerial(root->right);
return res;
}
//求next數組
int* getNextArray(string str2) {
if (str2.length() == 1) {
int* next = new int[1];
next[0] = -1;
return next;
}
int* next = new int[str2.length()];
next[0] = -1;
next[1] = 0;
int i = 2;
int cn = 0;
while (i < str2.length()) {
if (str2[i - 1] == str2[cn]) {
next[i++] = ++cn;
}
else if (cn > 0) {
cn = next[cn];
}
else {
next[i++] = 0;
}
}
return next;
}
//KMP算法返回子串在母串出現位置
int getIndexOf(string str1, string str2) {
if (str1.length() == 0 || str2.length() == 0)
return -1;
int i1 = 0;
int i2 = 0;
int* next = getNextArray(str2);
while (i1 < str1.length() && i2 < str2.length()) {
if (str1[i1] == str2[i2]) {
i1++;
i2++;
}
else {
if (next[i2] == -1) {
i1++;
}
else {
i2 = next[i2];
}
}
}
return i2 == str2.length() ? i1 - i2 : -1;
}
void display(int res) {
if (res == -1)
cout << "Is not subTree" << endl;
else
cout << "Is subTree" << endl;
}
int main() {
TreeNode* tree1 = preCreate();
cout << "tree1:" << endl;
preOrder(tree1);
TreeNode* tree2 = preCreate();
cout << "tree2:" << endl;
preOrder(tree2);
TreeNode* tree3 = preCreate();
cout << "tree3:" << endl;
preOrder(tree3);
TreeNode* tree4 = preCreate();
cout << "tree4:" << endl;
preOrder(tree4);
string s1 = preSerial(tree1);
string s2 = preSerial(tree2);
string s3 = preSerial(tree3);
string s4 = preSerial(tree4);
cout << "s1:" <<s1 << endl;
cout <<"s2:" << s2 << endl;
cout << "s3:" << s3 << endl;
cout << "s4:" << s4 << endl;
int res1 = getIndexOf(s1, s2);
int res2 = getIndexOf(s1, s3);
int res3 = getIndexOf(s1, s4);
cout << "tree2:";
display(res1);
cout << "tree3:";
display(res2);
cout << "tree4:";
display(res3);
while (1);
return 0;
}
測試1:
測試結果:
3、判斷一個字符串是否爲一個子串重複得到
比如:ababababab
就可以由ab重複得到,返回Treu
比如abcabcabc
就可以由abc重複得到,返回True
否則返回false
這也是kmp的變形