দুটি সিকোয়েন্স দেওয়া হয়েছে, একটির শেষ এবং অন্যটির শুরুতে সর্বাধিক ওভারল্যাপটি সন্ধান করুন


11

নিম্নলিখিত সমস্যাটি সমাধান করার জন্য আমার একটি কার্যকর (সিউডো) কোডের সন্ধান করতে হবে:

এর (অগত্যা স্বতন্ত্র নয়) পূর্ণসংখ্যার দুই সিকোয়েন্স দেওয়া (a[1], a[2], ..., a[n])এবং (b[1], b[2], ..., b[n]), সর্বোচ্চ খুঁজে dযেমন যে a[n-d+1] == b[1], a[n-d+2] == b[2]..., এবং a[n] == b[d]

এটি হোমওয়ার্ক নয়, যথাসম্ভব অনেক মাত্রা সহ দুটি টেনার চুক্তি করার চেষ্টা করার সময় আমি আসলে এটি নিয়ে এসেছি। আমি সন্দেহ করি একটি দক্ষ অ্যালগরিদম বিদ্যমান (সম্ভবত O(n)?), তবে আমি এমন কিছু নিয়ে আসতে পারি না O(n^2)। সর্বাধিক আঘাত না হওয়া পর্যন্ত প্রয়োজনীয় শর্তটি পরীক্ষা করতে আইটেমগুলির অভ্যন্তরীণ লুপটি এ O(n^2)পদ্ধতির সুস্পষ্ট লুপ dএবং তারপরে হবে d। তবে আমি সন্দেহ করি এর থেকে আরও ভাল কিছু সম্ভব।


যদি আপনার অ্যারেতে কোনও গ্রুপের জন্য কোনও রোলিং হ্যাশ গণনা করা যায় তবে আমি মনে করি এটি আরও দক্ষতার সাথে করা যেতে পারে। উপাদানগুলির জন্য গণনা হ্যাশ b[1] to b[d]এবং তারপরে অ্যারে aকম্পিউট হ্যাশ এ যান a[1] to a[d]যদি এটি মেলে তবে এটি আপনার উত্তর, যদি a[2] to a[d+1]হ্যাশকে গণনা করে পুনরায় ব্যবহারের জন্য গণনা হ্যাশ না হয় a[1] to a[d]। তবে আমি জানি না যে অ্যারেতে থাকা বস্তুগুলি তাদের উপর ঘূর্ণায়মান হ্যাশের জন্য উপযুক্ত কিনা if
সোমডুড

2
@ বেকো দুঃখিত, আমি মনে করি আপনি শেষ পর্যন্ত কী অর্জন করার চেষ্টা করছেন তা অবশেষে আমি বুঝতে পারি। যার aশুরুতে সর্বাধিক ওভারল্যাপটি সন্ধান করা bএই মত
ব্যবহারকারী 3386109

1
আমার কাছে মনে হচ্ছে সমস্যাটি স্ট্রিং মেলিংয়ের একটি প্রকরণ, যা নুথ – মরিস – প্র্যাট অ্যালগরিদমের কোনও প্রকরণের সাথে সমাধান করা যেতে পারে । চলমান সময় হবে হে (মি + N) যেখানে mউপাদান সংখ্যা a, এবং nউপাদানের সংখ্যা b। দুর্ভাগ্যক্রমে, কেএমপি-র সাথে কীভাবে এটি গ্রহণ করতে হয় তা সম্পর্কে আমার কাছে পর্যাপ্ত অভিজ্ঞতা নেই।
ব্যবহারকারী 3386109

1
@ ব্যবহারকারী 3386109 আমার সমাধানটি হাবন ফাংশন হিসাবে হর্নারের পদ্ধতিটি ব্যবহার করে রবিন-কার্প নামে একটি স্ট্রিং মিলে যাওয়া অ্যালগরিদমের একটি ভিন্নতা ।
ড্যানিয়েল

1
@ ড্যানিয়েল আহ, আমি জানতাম যে আমি কোথাও রোলিং হ্যাশ ব্যবহার করেছি, তবে কোথায় তা মনে করতে পারিনি :)
ইউজার 3386109

উত্তর:


5

আপনি z অ্যালগরিদম , একটি লিনিয়ার সময় ( O (n) ) অ্যালগরিদম ব্যবহার করতে পারেন যে:

দৈর্ঘ্যের n এর একটি স্ট্রিং এস দেওয়া , জেড অ্যালগরিদম একটি অ্যারে জে উত্পাদন করে যেখানে জেড [i] এস থেকে শুরু হওয়া দীর্ঘতম স্তরটির দৈর্ঘ্য যা [i] যা এস এর একটি উপসর্গও

(আপনি আপনার অ্যারে কনক্যাটেনেট প্রয়োজন + + একটি ) এবং প্রথম পর্যন্ত ফলে নির্মাণ শৃঙ্খলার অ্যালগরিদম চালানোর আমি যেমন যে জেড [আমি] + + আমি == মি + + এন

উদাহরণস্বরূপ, একটি = [1, 2, 3, 6, 2, 3] ও বি = [2, 3, 6, 2, 1, 0] এর জন্য উপসংহারটি হবে [2, 3, 6, 2, 1 , 0, 1, 2, 3, 6, 2, 3] যা জেড [10] = 2 পরিপূর্ণ জেড [i] + i = 12 = মি + এন উপার্জন করবে ।


সুন্দর! ধন্যবাদ।
বেকো

3

ও (এন) সময় / স্থান জটিলতার জন্য, কৌশলটি প্রতিটি অনুচ্ছেদের জন্য হ্যাশগুলি মূল্যায়ন করে। অ্যারে বিবেচনা করুন b:

[b1 b2 b3 ... bn]

হর্নারের পদ্ধতিটি ব্যবহার করে , আপনি প্রতিটি অনুচ্ছেদের জন্য সম্ভাব্য সমস্ত হ্যাশ মূল্যায়ন করতে পারেন। একটি বেস মান বাছাই করুন B(আপনার উভয় অ্যারে যে কোনও মানের চেয়ে বড়):

from b1 to b1 = b1 * B^1
from b1 to b2 = b1 * B^1 + b2 * B^2
from b1 to b3 = b1 * B^1 + b2 * B^2 + b3 * B^3
...
from b1 to bn = b1 * B^1 + b2 * B^2 + b3 * B^3 + ... + bn * B^n

নোট করুন যে আপনি পূর্ববর্তী ক্রমের ফলাফলটি ব্যবহার করে ও (1) সময়ে প্রতিটি ক্রম মূল্যায়ন করতে পারেন, সুতরাং সমস্ত কাজের জন্য ও (এন) ব্যয় হয়।

এখন আপনার কাছে একটি অ্যারে রয়েছে Hb = [h(b1), h(b2), ... , h(bn)], Hb[i]হ্যাশটি এখনও b1পর্যন্ত bi

অ্যারের জন্য একই জিনিস করুন a, তবে একটি সামান্য কৌশল দ্বারা:

from an to an   =  (an   * B^1)
from an-1 to an =  (an-1 * B^1) + (an * B^2)
from an-2 to an =  (an-2 * B^1) + (an-1 * B^2) + (an * B^3)
...
from a1 to an   =  (a1   * B^1) + (a2 * B^2)   + (a3 * B^3) + ... + (an * B^n)

আপনাকে অবশ্যই লক্ষ্য রাখতে হবে যে, আপনি যখন এক ক্রম থেকে অন্য ক্রমটি চলে যান, আপনি পুরো পূর্বের ক্রমটি বি দ্বারা গুণন করে এবং বি দ্বারা গুণিত নতুন মান যুক্ত করেন উদাহরণস্বরূপ:

from an to an =    (an   * B^1)

for the next sequence, multiply the previous by B: (an * B^1) * B = (an * B^2)
now sum with the new value multiplied by B: (an-1 * B^1) + (an * B^2) 
hence:

from an-1 to an =  (an-1 * B^1) + (an * B^2)

এখন আপনার কাছে একটি অ্যারে রয়েছে Ha = [h(an), h(an-1), ... , h(a1)], Ha[i]হ্যাশটি এখনও aiপর্যন্ত an

এখন, আপনি n থেকে 1 পর্যন্ত Ha[d] == Hb[d]সমস্ত dমানের জন্য তুলনা করতে পারেন , যদি সেগুলি মেলে, আপনার কাছে আপনার উত্তর রয়েছে।


মনোযোগ : এটি একটি হ্যাশ পদ্ধতি, মানগুলি বড় হতে পারে এবং আপনাকে একটি দ্রুত ক্ষতিকারক পদ্ধতি এবং মডুলার গাণিতিকগুলি ব্যবহার করতে হতে পারে , যা আপনাকে (সংক্ষেপে) সংঘর্ষ দিতে পারে , এই পদ্ধতিটি সম্পূর্ণ নিরাপদ নয় making একটি ভাল অনুশীলন হ'ল একটি বেসকে Bসত্যিকারের বড় সংখ্যা হিসাবে বেছে নেওয়া (আপনার অ্যারেগুলির বৃহত্তম মানের চেয়ে কমপক্ষে বড়)। আপনার প্রতিটি স্তরে সংখ্যার সীমা অতিক্রম করতে পারে সেজন্য আপনারও যত্নবান হওয়া উচিত, সুতরাং আপনাকে Kপ্রতিটি ক্রিয়াকলাপে ( মডুলো ) ব্যবহার Kকরতে হবে (যেখানে প্রাইম বড় হতে পারে B)।

এর অর্থ হ'ল দুটি ভিন্ন সিকোয়েন্সগুলিতে একই হ্যাশ থাকতে পারে তবে দুটি সমান ক্রমের সবসময় একই হ্যাশ থাকবে।


আপনি কি দয়া করে এই উত্তরটি উত্সের প্রয়োজনীয়তার মূল্যায়ন দিয়ে শুরু করতে পারেন?
গ্রেইবার্ড

2

এটি প্রকৃতপক্ষে রৈখিক সময়, ও (এন) এবং ও (এন) অতিরিক্ত জায়গায় করা যেতে পারে। আমি ধরে নেব ইনপুট অ্যারেগুলি চরিত্রের স্ট্রিং, তবে এটি প্রয়োজনীয় নয়।

একটি সরল পদ্ধতি হবে - মিলে পর অক্ষর আছে যা সমান - একটি চরিত্র মেলে না, এবং ফিরে যেতে K-1 ইউনিট একটি সূচক পুনঃসেট , এবং তারপর সেখান থেকে মেলানোর প্রক্রিয়া শুরু। এটি পরিষ্কারভাবে একটি ও (n²) সবচেয়ে খারাপ ক্ষেত্রে উপস্থাপন করে।

এই ব্যাকট্র্যাকিংয়ের প্রক্রিয়াটি এড়াতে, আমরা পর্যবেক্ষণ করতে পারি যে শেষ কে -১ টি অক্ষরগুলি স্ক্যান করার সময় আমরা খ [0] অক্ষরটির মুখোমুখি না হয়ে থাকলে ফিরে যাওয়া কার্যকর নয়। আমরা যদি করেনি যে চরিত্র খুঁজে, তাহলে সেই অবস্থান থেকে backtracking শুধুমাত্র দরকারী, যদি সেই হবে সাবস্ট্রিং আকারের আমরা পর্যায়ক্রমিক পুনরাবৃত্তি ছিল।

উদাহরণস্বরূপ, যদি আমরা "abcabc" কোথাও সাবস্ট্রিং তাকান একটি , এবং "abcabd", এবং আমরা যে চূড়ান্ত চরিত্র সাথে মেলে না, আমরা বিবেচনা করতে হবে যে একটি সফল ম্যাচ দ্বিতীয় "A" এ শুরু হতে পারে স্ট্রিংগুলিতে এবং আমাদের তুলনা চালিয়ে যাওয়ার আগে আমাদের বর্তমান সূচকটি অনুসারে পিঠে সরানো উচিত ।

এরপরে ধারণাটি হ'ল স্ট্রিং বিয়ের উপর ভিত্তি করে কিছু প্রিপ্রসেসিং করা -এর বি -রেফারেন্সগুলিতে লগ করার জন্য যা কোনও মিল নেই কিনা তা পরীক্ষা করতে দরকারী। সুতরাং উদাহরণস্বরূপ, বি যদি "acaacaacd" হয়, আমরা এই 0-ভিত্তিক ব্যাকরফারেন্সগুলি (প্রতিটি চরিত্রের নীচে রাখি) সনাক্ত করতে পারি:

index: 0 1 2 3 4 5 6 7 8
b:     a c a a c a a c d
ref:   0 0 0 1 0 0 1 0 5

উদাহরণস্বরূপ, যদি আমরা আছে একটি সমান "acaacaaca" প্রথম মেলেনি চূড়ান্ত চরিত্রে ঘটবে। উপরের তথ্যগুলি পরে আলগোরিদিমকে বি তে ফিরে সূচক 5 তে ফিরে যেতে বলে , "অ্যাকাক" সাধারণ কারণ। এবং তারপর শুধুমাত্র বর্তমান সূচক পরিবর্তন আমরা বর্তমান সূচিতে ম্যাচিং চালিয়ে যেতে পারেন একটি । এই উদাহরণে চূড়ান্ত চরিত্রের মিলটি তখন সফল হয়।

এই সঙ্গে আমরা অনুসন্ধান নিখুত এবং নিশ্চিত করুন যে সূচক করতে পারেন একটি সবসময় সামনে অগ্রসর হতে পারে।

জাভাস্ক্রিপ্টে সেই ধারণার বাস্তবায়ন এখানে কেবলমাত্র সেই ভাষার সর্বাধিক প্রাথমিক বাক্য গঠন ব্যবহার করে:

function overlapCount(a, b) {
    // Deal with cases where the strings differ in length
    let startA = 0;
    if (a.length > b.length) startA = a.length - b.length;
    let endB = b.length;
    if (a.length < b.length) endB = a.length;
    // Create a back-reference for each index
    //   that should be followed in case of a mismatch.
    //   We only need B to make these references:
    let map = Array(endB);
    let k = 0; // Index that lags behind j
    map[0] = 0;
    for (let j = 1; j < endB; j++) {
        if (b[j] == b[k]) {
            map[j] = map[k]; // skip over the same character (optional optimisation)
        } else {
            map[j] = k;
        }
        while (k > 0 && b[j] != b[k]) k = map[k]; 
        if (b[j] == b[k]) k++;
    }
    // Phase 2: use these references while iterating over A
    k = 0;
    for (let i = startA; i < a.length; i++) {
        while (k > 0 && a[i] != b[k]) k = map[k];
        if (a[i] == b[k]) k++;
    }
    return k;
}

console.log(overlapCount("ababaaaabaabab", "abaababaaz")); // 7

যদিও নেস্টেড whileলুপ রয়েছে তবে এগুলির মোট n এর চেয়ে বেশি পুনরাবৃত্তি নেই । এটি কারণ শরীরে k এর মান কঠোরভাবে হ্রাস পায় এবং whileনেতিবাচক হয়ে উঠতে পারে না। এটি কেবল তখনই ঘটতে পারে যখন k++মৃত্যুদণ্ড কার্যকর করা হয়েছিল যে এরকম হ্রাসের জন্য পর্যাপ্ত জায়গা দেওয়ার জন্য বহুবার। সুতরাং সর্বোপরি মৃত্যুদণ্ড কার্যকর হওয়ার whileচেয়ে শরীরের বেশি মৃত্যুদণ্ড কার্যকর করা যাবে না k++এবং পরেরটি স্পষ্টত O (n)।

সম্পূর্ণ করার জন্য, আপনি উপরের মত একই কোডটি পেতে পারেন, তবে একটি ইন্টারেক্টিভ স্নিপেটে: আপনি নিজের স্ট্রিংগুলি ইনপুট করতে পারেন এবং ফলাফলটি ইন্টারেক্টিভভাবে দেখতে পারেন:

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.