字符串同源异构查找

字符串同源异构
相同字符组成的,顺序不一样的字符串。从一个源字符串中查询子字符串。要满足子字符串的字符,在源字符中顺序存在,不能分割存在。如一个是源string: caabcb 目标string: acabb 。源字符中aabcb就是目标字符串(acabb )的同源异构体
构造窗口模式查询
1、需要构建目标string: acabb的字符串个数表。如欠债表:a=2,c=1,b=2
2、定义一个目标窗口和目标字符串一样大小 以及是否找到了同源异构的flag,默认flag=0,可以找到满足的同源异构体
2、第一个窗口个数遍历:从源来字符串里从头遍历,如果一个字符串出现在欠债表里,则欠债表里的相应字符串的个数减一,如果该字符个数小于0,则flag加1。标示此时窗口中的该字符的个数比目标串的该字符个数多。第一个窗口都是入窗的数据。
3、当第一1个遍历完窗口[0…M-1]的大小的数据后,下一个窗口遍历是[1…M],
这是需要处理逻辑和第一次遍历窗口的逻辑不一样
第二次以及以后窗口向左边移动的时候,如果进入窗口的字符,如果在欠债表里该字符个数已经小于等于0了,那么再进入窗口中,flag++(ps:标示比目标串中该字符又多1个)。欠债表里的相应字符串的个数减一。
从左边出去的窗口数据[R-M] ,如果该字符的个数已经小于0,则flag–(ps:标示比目标串中该字符的个数可以少了一个),欠债表里该字符串的个数+1.(ps:我已经出窗口了,不再比较了,原来减少的字符可以还原了)
代码实现*

public class CommpareString {

    /**
     * 有2个string,一个是源string:  caabcb  目标string: acabb
     * 从源string里找到 目标的同源异构
     * 返回同源异构的起始位置
     */

    /**
     * 根据目标串新建欠债表,每个字符出现次数
     * a=2
     * c=1
     * b=2
     */

    public static void main(String [] args){

        CommpareString commpareString = new CommpareString();
        int a= commpareString.commpareStr("acabb","caabcb");
        System.out.println(a);
    }


    public int commpareStr(String tarskStr,String orgStr ){

       // String tarskStr="acabb";
        char tar [] = tarskStr.toCharArray();
        int count []= new int[256];
        for(int i=0;i<tar.length;i++){
            count[tar[i]]++;
        }
        //count[a]=2  count[c]=1 count[b]=2

        //定义一个目标窗口和目标字符串一样大小 以及是否找到了同源异构的flag,flag=0代表找到了,flag=整数则表示多余字符,为负数,则缺少字符
        //什么叫欠债表呢
        //从源来字符串里从头遍历,如果一个字符串出现在欠债表里,则欠债表里的相应字符串的个数减一,如果个数小于0,则flag--
        //当第一次遍历完窗口[0...M-1]的大小的数据后,下一个窗口遍历是[1...M],
        //这是需要处理逻辑和第一次遍历窗口的逻辑不一样
        //第二次以及以后窗口向左边移动的时候,如果进入窗口的字符,如果在欠债表里已经<=0,那么flag++,且欠债表里的相应字符串的个数减一
        //从左边出去的窗口数据[R-M] 以及<0,则flag--,则欠债表里响应字符串的个数+1

        //进入窗口的字符,在欠债表里个数-1,出去窗口的字符,在欠债表里个数+1(ps:还给欠债表)


        int M=tarskStr.length();
        char org[] =orgStr.toCharArray();
        int R=0;
        int flag=0;
        for(;R<M;R++){
            System.out.println(org[R] +"="+count[org[R]]);
            if(count[org[R]]--<=0){//在-1之前已经是0了,如果再次-1必然是负数,flag+1(我欠表里字符一个)
                flag++;
            }
        }


        for(;R<org.length;R++){
            if(flag==0)
                return R-M;

            if(count[org[R]]--<=0){
                flag++;
            }

            if(count[org[R-M]]++ <0){
                flag--;
            }
        }
        return flag==0?R-M:-1;
    }
}

窗口的作用
窗口的大小和目标串一致。进入窗口的字符,从cout中减1,出去窗口的字符,从cout中加1。flag是比较器,如果flag++,标识欠目标串的。flag–,标识还给目标串的。最后如果flag==0,标识匹配到了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值