校招算法笔面试 | 校招笔面试真题-字符串是否由子串拼接

题目## 题目

题目链接

解题思路

  1. 这是一个字符串首尾拼接问题,需要判断一个字符串是否由某个子串重复拼接而成
  2. 解题步骤:
    • 将原字符串拼接自身得到双倍长度的字符串
    • 去掉拼接后字符串的首尾字符
    • 在处理后的字符串中查找原字符串
    • 如果找到且位置在前半部分,则说明存在满足条件的子串

代码

#include <iostream>
#include <string>
using namespace std;

string findSubstring(string s) {
    int n = s.length();
    
    // 将字符串拼接自身并去掉首尾
    string doubled = s + s;
    string trimmed = doubled.substr(1, 2 * n - 2);
    
    // 在处理后的字符串中查找原字符串
    size_t pos = trimmed.find(s);
    if(pos != string::npos && pos < n) {
        return s.substr(0, pos + 1);
    }
    return "false";
}

int main() {
    string s;
    cin >> s;
    cout << findSubstring(s) << endl;
    return 0;
}
import java.util.Scanner;

public class Main {
    public static String findSubstring(String s) {
        int n = s.length();
        
        // 将字符串拼接自身并去掉首尾
        String doubled = s + s;
        String trimmed = doubled.substring(1, 2 * n - 1);
        
        // 在处理后的字符串中查找原字符串
        int pos = trimmed.indexOf(s);
        if(pos != -1 && pos < n) {
            return s.substring(0, pos + 1);
        }
        return "false";
    }
    
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String s = sc.nextLine();
        System.out.println(findSubstring(s));
    }
}
def find_substring(s):
    n = len(s)
    
    # 将字符串拼接自身并去掉首尾
    doubled = s + s
    trimmed = doubled[1:2*n-1]
    
    # 在处理后的字符串中查找原字符串
    pos = trimmed.find(s)
    if pos != -1 and pos < n:
        return s[:pos+1]
    return "false"

s = input()
print(find_substring(s))

算法及复杂度

  • 算法:字符串匹配
  • 时间复杂度: O ( n ) \mathcal{O}(n) O(n) - n n n 为字符串长度
  • 空间复杂度: O ( n ) \mathcal{O}(n) O(n) - 需要存储拼接后的字符串

题目链接

#字符串旋转
解析问题:对于输入字符串通过“;”拆分为字符串A和B。首先判断字符串A和B的长度是否相同,若不同直接输出flase,若相同进一步判断A是否可以通过旋转得到B:

暴力求解(一):

根据字符串A的长度L,通过循环从字符串下标1到L-2处拆分为两个字符串str1和str2,再将两者按照str2 str1的顺序组成新字符串A1与B进行比较,若A1与B相同,跳出循环输出true,若循环结束没有相同情况输出flase(通过一个标志变量判断是否提前退出循环)。

#include <bits stdc++.h>
using namespace std;
int main(){
    string s,A,B,A1,str1,str2;
    cin &gt;&gt; s;
    A = s.substr(0, s.find(';'));
    B = s.substr(s.find(';')+1,string::npos);
    if(A.length()!=B.length()) {
    	cout&lt;&lt;"false"&lt;<endl; return 0; } 标注变量判断是否提前退出循环 ,ture为提前退出循环,flase为正常结束循环 bool flag="true;" for(int i="0;i<A.length()-1;i++){" str1="A.substr(0," i); str2="A.substr(i,string::npos);" a1="str2" + str1; if(a1="=" b){ break; if(flag) cout<<"true"<<endl; else cout<<"false"<<endl; ```## 暴力求解优化(二): 在循环中,将字符串下标0到l-2处拆分为两个字符串str1和str2之前,判断拆分点处的字符与字符串b的首字符是否相同。若不相同拼接得到的字符串a1一定与b不相同,所以直接跳过本次拆分、拼接和比较过程,判断下一个拆分点。 #include <bits stdc++.h>
using namespace std;
int main(){
    string s,A,B,A1,str1,str2;
    cin &gt;&gt; s;
    A = s.substr(0, s.find(';'));
    B = s.substr(s.find(';')+1,string::npos);
    if(A.length()!=B.length()) {
    	cout&lt;&lt;"false"&lt;<endl; return 0; } 标注变量判断是否提前退出循环 ,ture为提前退出循环,flase为正常结束循环 bool flag="true;" for(int i="0;i<A.length()-1;i++){" 判断拆分点处字符与字符串b首字符是否相等 if(a[i] !="B[0])" continue; str1="A.substr(0," i); str2="A.substr(i,string::npos);" a1="str2" + str1; if(a1="=" b){ break; if(flag) cout<<"true"<<endl; else cout<<"false"<<endl; ```## 最简方法(三): 将两个字符串a拼接为a1,判断a1字符串是否包含字符串b。例如 字符串a:youzan a1:youzanyouzan a1包含b:输出true #include<iostream> 
using namespace std; 
int main()
{
    string s;
    cin &gt;&gt; s;
    string A = s.substr(0, s.find(';'));
    string B = s.substr(s.find(';')+1,string::npos);
    if(A.length()!=B.length()) {
    	cout&lt;&lt;"false"&lt;</endl;></endl;></bits>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值