এটি বোঝা যাচ্ছে যে সবচেয়ে খারাপ পরিস্থিতিটি হ'ল O(N)
, খুব সুন্দর কিছু মাইক্রো-অপ্টিমাইজেশন রয়েছে।
নিষ্পাপ পদ্ধতিটি প্রতিটি চরিত্রের জন্য একটি অক্ষর তুলনা এবং পাঠ্য সমাপ্তির সম্পাদন করে।
একটি সেন্ডিনেল (অর্থাত্ পাঠ্যের শেষে লক্ষ্য অক্ষরের অনুলিপি) ব্যবহার করে প্রতিটি চরিত্রের তুলনা করার সংখ্যা হ্রাস করে 1।
বিট টুইডলিং স্তরে রয়েছে:
#define haszero(v) ( ((v) - 0x01010101UL) & ~(v) & 0x80808080UL )
#define hasvalue(x, n) ( haszero((x) ^ (~0UL / 255 * (n))) )
কোনও শব্দের কোনও বাইট ( x
) এর একটি নির্দিষ্ট মান ( n
) রয়েছে কিনা তা জানতে ।
স্যুবপ্রেসেশন v - 0x01010101UL
, যখনই সম্পর্কিত বাইট v
শূন্য বা তার চেয়ে বেশি হয় কোনও বাইটে উচ্চ বিট সেটকে মূল্যায়ন করে 0x80
।
উপ-এক্সপ্রেশনটি ~v & 0x80808080UL
বাইটগুলিতে সেট উচ্চ বিটগুলিতে মূল্যায়ন করে যেখানে বাইটটির v
উচ্চ বিট সেট থাকে না (তাই বাইটটি কম ছিল 0x80
)।
এই দুটি উপ-এক্সপ্রেশন ( haszero
) প্রকাশের ফলে ফলাফলটি উচ্চ বিটস সেট হয় যেখানে বাইটগুলি v
শূন্য ছিল, যেহেতু 0x80
প্রথম উপ-এক্সপ্রেশনটির চেয়ে বেশি মানের কারণে উচ্চ বিটগুলি দ্বিতীয় দ্বারা মুখোশযুক্ত হয় (এপ্রিল 27, 1987 দ্বারা অ্যালান মাইক্রফ্ট)।
এখন আমরা x
এমন কোনও শব্দের সাথে ( ) পরীক্ষা করার মানটি XOR করতে পারি যা আমাদের আগ্রহী ( n
) এর সাথে বাইট মানটি পূর্ণ হয়েছে । যেহেতু নিজের সাথে একটি মান জোর করা ফলস্বরূপ শূন্য বাইট এবং ননজারো হয় অন্যথায়, আমরা ফলাফলটি পাস করতে পারি haszero
।
এটি প্রায়শই একটি সাধারণ strchr
বাস্তবায়নে ব্যবহৃত হয় ।
(স্টিফেন এম বেনেট 13 ডিসেম্বর, ২০০৯ এ পরামর্শ দিয়েছেন Further আরও বিশদ বিট টুইডলিং হ্যাকস-এ )।
দ্রষ্টব্য
এই কোডটি 1111
a এর পাশের যেকোন সংমিশ্রণের জন্য ভেঙে গেছে0
হ্যাক নিষ্ঠুর শক্তি পরীক্ষা পাস (শুধু ধৈর্য ধরুন):
#include <iostream>
#include <limits>
bool haszero(std::uint32_t v)
{
return (v - std::uint32_t(0x01010101)) & ~v & std::uint32_t(0x80808080);
}
bool hasvalue(std::uint32_t x, unsigned char n)
{
return haszero(x ^ (~std::uint32_t(0) / 255 * n));
}
bool hasvalue_slow(std::uint32_t x, unsigned char n)
{
for (unsigned i(0); i < 32; i += 8)
if (((x >> i) & 0xFF) == n)
return true;
return false;
}
int main()
{
const std::uint64_t stop(std::numeric_limits<std::uint32_t>::max());
for (unsigned c(0); c < 256; ++c)
{
std::cout << "Testing " << c << std::endl;
for (std::uint64_t w(0); w != stop; ++w)
{
if (w && w % 100000000 == 0)
std::cout << w * 100 / stop << "%\r" << std::flush;
const bool h(hasvalue(w, c));
const bool hs(hasvalue_slow(w, c));
if (h != hs)
std::cerr << "hasvalue(" << w << ',' << c << ") is " << h << '\n';
}
}
return 0;
}
একটি উত্তরের জন্য প্রচুর পরিমাণে অগ্রগতি যা অনুমানটিকে একটি চরারেক্টর = একটি বাইট করে তোলে যা আজকাল আর মানক নয়
মন্তব্যের জন্য আপনাকে ধন্যবাদ।
উত্তরটি হ'ল মাল্টি-বাইট / ভেরিয়েবল-প্রস্থের এনকোডিংগুলি সম্পর্কিত একটি রচনা :-) (সমস্ত ন্যায্যতার সাথে এটি আমার দক্ষতার ক্ষেত্র নয় এবং আমি নিশ্চিত নই যে এটি ওপি কী সন্ধান করছে)।
যাইহোক এটি আমার কাছে মনে হয় যে উপরের ধারণা / কৌশলগুলি কিছুটা এমবিই (বিশেষত স্ব-সিঙ্ক্রোনাইজিং এনকোডিংগুলি ) এর সাথে মানিয়ে নেওয়া যেতে পারে :
- জোহানের মন্তব্যে উল্লিখিত হিসাবে হ্যাকটি 'সহজেই' ডাবল বাইট বা যে কোনও কিছুর জন্য কাজ করতে বাড়ানো যেতে পারে (অবশ্যই আপনি এটি খুব বেশি প্রসারিত করতে পারবেন না);
- একটি সাধারণ ফাংশন যা একটি মাল্টিবাইট অক্ষর স্ট্রিংয়ে একটি অক্ষর সনাক্ত করে:
- সেন্ডিনেল কৌশলটি একটু দূরদর্শিতার সাথে ব্যবহার করা যেতে পারে।