获取两个字符串中最长相同子串

24 篇文章 0 订阅
2 篇文章 0 订阅

获取两个字符串中最长相同子串。比如: str1 = "abcwerthelloyuiodef ";str2 = “cvhellobnm” 提示:将短的那个串进行长度依次递减的子串与较长的串比较。 int length = str2.length(); // 用于控制子串的长度

方法一:暴力法
1.计算str2 的所有子串数(排列组合),保存在n中

int n = 0;

        for (int i = 0; i < str2.length(); i++) {

            n += i;

        }

2.创建一个字符数组保存str2的所有子串,用String的Substring切割得到子串,加一个count计数器

String[] s = new String[n];
        int count = 0;
        for (int k = 0; k < str2.length() - 1; k++) {
            for (int i = k; i < str2.length() - 1; i++) {

                s[count++] = str2.substring(k, i + 2);


            }

        }

3.创建新的数组s1来保存符合条件的子串,遍历s数组,indexOf(s[i])判断每一个子串是否有匹配项,将匹配的字符串存进s1中

String[] s1 = new String[count];

  
        int m = 0;
        for (int i = 0; i < count; i++) {


            if (str1.indexOf(s[i]) > 0) {

                s1[m++] = s[i];


            }


        }

4.此时s1中存放的都是两个字符串中的相同子串,找到字符串元素的最大长度,不能直接输出最长的子串,此时不确定长度最长的子串的个数,所以拿到最长长度就够了

int maxLength = 0;


        for (int j = 0; j < m; j++) {


            if (s1[j].length() > maxLength) {
                maxLength = s1[j].length();
            }


        }

5.遍历数组,长度等于最长长度的字符串全部输出,s1不是完美数组,所以要进行非空判断

for (String i : s1) {

            if (i != null) {

                if (i.length() == maxLength) {

                    System.out.println(i);

                }


            }


        }

全部代码

 @Test
    public void test4() {


        String str1 = "abcwerthelloyuhelloiodef ";
        String str2 = "cvhellobnm";
        int n = 0;

        for (int i = 0; i < str2.length(); i++) {

            n += i;

        }
        System.out.println(n);


        String[] s = new String[n];
        int count = 0;
        for (int k = 0; k < str2.length() - 1; k++) {
            for (int i = k; i < str2.length() - 1; i++) {

                s[count++] = str2.substring(k, i + 2);


            }

        }


        String[] s1 = new String[count];


        int m = 0;
        for (int i = 0; i < count; i++) {


            if (str1.indexOf(s[i]) > 0) {

                s1[m++] = s[i];


            }


        }

        int maxLength = 0;


        for (int j = 0; j < m; j++) {


            if (s1[j].length() > maxLength) {
                maxLength = s1[j].length();
            }


        }
        for (String i : s1) {

            if (i != null) {

                if (i.length() == maxLength) {

                    System.out.println(i);

                }


            }


        }


    }

优化:将2.3.4步操作整合,减少两次循环

    @Test
    public void test4() {


        String str1 = "abcwerthelloyuhelloiodef ";
        String str2 = "cvhellobnm";
        int n = 0;

        for (int i = 0; i < str2.length(); i++) {

            n += i;

        }


        String[] s = new String[n];

        int m = 0;
        int maxLength = 0;
        String[] s1 = new String[n];
        for (int k = 0; k < str2.length() - 1; k++) {
            for (int i = k; i < str2.length() + 1; i++) {

                if (str1.indexOf(str2.substring(k, i)) > 0) {

                    s1[m] = str2.substring(k, i);
                    if (s1[m].length() > maxLength) {
                        maxLength = s1[m].length();
                    }
                    m++;


                }


            }


        }


        for (int i = 0; i < s1.length - 1; i++) {

            if (s1[i] != null) {
                if (s1[i].length() == maxLength) {

                    System.out.println(s1[i]);

                }
            }


        }


    }

方法二:

算法思路:

1、把两个字符串分别以行和列组成一个二维矩阵。

 int maxLen = 0;
        int maxEnd = 0;
        int[][] record = new int[str1.length()][str2.length()];

2、比较二维矩阵中每个点对应行列字符中否相等,相等的话值设置为1,否则设置为0。

if (str1.charAt(i) == str2.charAt(j)) {

                    if (i == 0 || j == 0) {

                        record[i][j] = 0;

                    } else {

                        record[i][j] = record[i - 1][j - 1] + 1;

                    }


                } else {

                    record[i][j] = 0;
                }

3、通过查找出值为1的最长对角线就能找到最长公共子串。

				if (record[i][j] > maxLen) {

                    maxLen = record[i][j];
                    maxEnd = i;

                }
               
String substring = str1.substring(maxEnd - maxLen + 1, maxEnd + 1);
        System.out.println(substring);

全部代码



@Test
    public void test() {


        String str1 = "abcwerthelloyuiodef ";
        String str2 = "cvhellobnm";

        int maxLen = 0;
        int maxEnd = 0;
        int[][] record = new int[str1.length()][str2.length()];


        for (int i = 0; i < str1.length(); i++) {

            for (int j = 0; j < str2.length(); j++) {

                if (str1.charAt(i) == str2.charAt(j)) {

                    if (i == 0 || j == 0) {

                        record[i][j] = 0;

                    } else {

                        record[i][j] = record[i - 1][j - 1] + 1;

                    }


                } else {

                    record[i][j] = 0;
                }

                if (record[i][j] > maxLen) {

                    maxLen = record[i][j];
                    maxEnd = i;

                }


            }

        }
		String substring = str1.substring(maxEnd - maxLen + 1, maxEnd + 1);
        System.out.println(substring);
        }
        

转自:https://blog.csdn.net/qq_25800311/article/details/81607168

方法三:将短的那个串进行长度依次递减的子串与较长的串比较

@Test
    public void work3() {
        String str1 = "abcwerthelloyuiodef";
        String str2 = "cvhellobnm";
        int length = str2.length(); // 用于控制子串的长度

        l1 : while (length >= 0) {
            // 以length为长度从str2中取子串
            int begin = 0; // 开始索引
            int end = begin + length; // 结束索引
            while (end <= str2.length()) { // 只要子串的右边界没有越过短串的右面
                String substring = str2.substring(begin, end);
                if (str1.indexOf(substring) != -1) { //if (长串包含子串) {
                    //总任务完成
                    System.out.println(substring);
                    break l1;
                }
                begin++; // 右移开始索引
                end = begin + length; // 为了保证子串的长度固定, 结束索引也要变化.
            }
            // 长度不合适, 长度--
            length--;
        }
    }
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十三幺Shisanyao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值